Support for C++ constructors/destructors.
authorMarek Michalkiewicz <marekm@amelek.gda.pl>
Sat, 1 Jun 2002 23:33:47 +0000 (01:33 +0200)
committerMarek Michalkiewicz <marekm@gcc.gnu.org>
Sat, 1 Jun 2002 23:33:47 +0000 (23:33 +0000)
* config/avr/avr.c (avr_output_function_epilogue): Jump to exit()
instead of looping if main() returns.
(asm_file_start): Output global symbols that cause .data and .bss
initialization code to be linked in, unconditionally for now.
(avr_asm_out_ctor, avr_asm_out_dtor): New functions.
* config/avr/avr.h (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): New.
(TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): New.
(LIBSTDCXX): New.
* config/avr/libgcc.S (_exit): Split in .fini9 and .fini0 sections.
(__tablejump__): New.
(__do_copy_data, __do_clear_bss): New.
(__do_global_ctors, __do_global_dtors): New.
* config/avr/t-avr (LIB1ASMFUNCS): Add _copy_data, _clear_bss,
_ctors, _dtors.

From-SVN: r54156

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/config/avr/avr.h
gcc/config/avr/libgcc.S
gcc/config/avr/t-avr

index f601740..391f551 100644 (file)
@@ -1,3 +1,21 @@
+2002-06-02  Marek Michalkiewicz  <marekm@amelek.gda.pl>
+
+       Support for C++ constructors/destructors.
+       * config/avr/avr.c (avr_output_function_epilogue): Jump to exit()
+       instead of looping if main() returns.
+       (asm_file_start): Output global symbols that cause .data and .bss
+       initialization code to be linked in, unconditionally for now.
+       (avr_asm_out_ctor, avr_asm_out_dtor): New functions.
+       * config/avr/avr.h (CTORS_SECTION_ASM_OP, DTORS_SECTION_ASM_OP): New.
+       (TARGET_ASM_CONSTRUCTOR, TARGET_ASM_DESTRUCTOR): New.
+       (LIBSTDCXX): New.
+       * config/avr/libgcc.S (_exit): Split in .fini9 and .fini0 sections.
+       (__tablejump__): New.
+       (__do_copy_data, __do_clear_bss): New.
+       (__do_global_ctors, __do_global_dtors): New.
+       * config/avr/t-avr (LIB1ASMFUNCS): Add _copy_data, _clear_bss,
+       _ctors, _dtors.
+
 2002-06-02  Neil Booth  <neil@daikokuya.demon.co.uk>
 
        * c4x/c4x.h (TARGET_CPU_CPP_BUILTINS): New.
index cf7b6c0..6176801 100644 (file)
@@ -67,6 +67,9 @@ static void   avr_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 static void   avr_unique_section PARAMS ((tree, int));
 static void   avr_encode_section_info PARAMS ((tree, int));
 
+static void   avr_asm_out_ctor PARAMS ((rtx, int));
+static void   avr_asm_out_dtor PARAMS ((rtx, int));
+
 /* Allocate registers from r25 to r8 for parameters for function calls */
 #define FIRST_CUM_REG 26
 
@@ -757,8 +760,18 @@ avr_output_function_epilogue (file, size)
   fprintf (file, "/* epilogue: frame size=%d */\n", size);
   if (main_p)
     {
-      fprintf (file, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
-      ++epilogue_size;
+      /* Return value from main() is already in the correct registers
+        (r25:r24) as the exit() argument.  */
+      if (AVR_MEGA)
+       {
+         fputs ("\t" AS1 (jmp,exit) "\n", file);
+         epilogue_size += 2;
+       }
+      else
+       {
+         fputs ("\t" AS1 (rjmp,exit) "\n", file);
+         ++epilogue_size;
+       }
     }
   else if (minimize && (frame_pointer_needed || live_seq > 4))
     {
@@ -4814,7 +4827,13 @@ asm_file_start (file)
   fputs ("__tmp_reg__ = 0\n" 
         "__zero_reg__ = 1\n"
         "_PC_ = 2\n", file);
-  
+
+  /* FIXME: output these only if there is anything in the .data / .bss
+     sections - some code size could be saved by not linking in the
+     initialization code from libgcc if one or both sections are empty.  */
+  fputs ("\t.global __do_copy_data\n", file);
+  fputs ("\t.global __do_clear_bss\n", file);
+
   commands_in_file = 0;
   commands_in_prologues = 0;
   commands_in_epilogues = 0;
@@ -5531,3 +5550,22 @@ avr_out_sbxx_branch (insn, operands)
     return AS1 (rjmp,%3);
   return "";
 }
+
+static void
+avr_asm_out_ctor (symbol, priority)
+     rtx symbol;
+     int priority;
+{
+  fputs ("\t.global __do_global_ctors\n", asm_out_file);
+  default_ctor_section_asm_out_constructor (symbol, priority);
+}
+
+static void
+avr_asm_out_dtor (symbol, priority)
+     rtx symbol;
+     int priority;
+{
+  fputs ("\t.global __do_global_dtors\n", asm_out_file);
+  default_dtor_section_asm_out_destructor (symbol, priority);
+}
+
index 6102a03..d26bafd 100644 (file)
@@ -1728,6 +1728,24 @@ do {                                                                         \
    `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
    used.  */
 
+/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
+   There are no shared libraries on this target, and these sections are
+   placed in the read-only program memory, so they are not writable.  */
+
+#undef CTORS_SECTION_ASM_OP
+#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"a\",@progbits"
+
+#undef DTORS_SECTION_ASM_OP
+#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"a\",@progbits"
+
+#define TARGET_ASM_CONSTRUCTOR avr_asm_out_ctor
+/* If defined, a function that outputs assembler code to arrange to
+   call the function referenced by SYMBOL at initialization time.  */
+
+#define TARGET_ASM_DESTRUCTOR avr_asm_out_dtor
+/* This is like `TARGET_ASM_CONSTRUCTOR' but used for termination
+   functions rather than initialization functions.  */
+
 #define EXTRA_SECTIONS in_progmem
 /* A list of names for sections other than the standard two, which are
    `in_text' and `in_data'.  You need not define this macro on a
@@ -2588,6 +2606,9 @@ extern int avr_case_values_threshold;
    If this macro is not defined, a default is provided that loads the
    standard C library from the usual place.  See `gcc.c'.  */
 
+#define LIBSTDCXX "-lgcc"
+/* No libstdc++ for now.  Empty string doesn't work.  */
+
 #define LIBGCC_SPEC \
   "%{!mmcu=at90s1*:%{!mmcu=attiny1*:%{!mmcu=attiny28: -lgcc }}}"
 /* Another C string constant that tells the GNU CC driver program how
index d324a21..8548a73 100644 (file)
@@ -637,11 +637,19 @@ __epilogue_restores__:
 #endif /* defined (L_epilogue) */
 
 #ifdef L_exit
-       .weak   _exit
+       .section .fini9,"ax",@progbits
+       .global _exit
        .func   _exit
 _exit:
-       rjmp    _exit
-.endfunc
+       .weak   exit
+exit:
+
+       /* Code from .fini8 ... .fini1 sections inserted by ld script.  */
+
+       .section .fini0,"ax",@progbits
+__stop_program:
+       rjmp    __stop_program
+       .endfunc
 #endif /* defined (L_exit) */
 
 #ifdef L_cleanup
@@ -658,6 +666,8 @@ _cleanup:
 __tablejump2__:
        lsl     r30
        rol     r31
+       .global __tablejump__
+__tablejump__:
 #if defined (__AVR_ENHANCED__)
        lpm     __tmp_reg__, Z+
        lpm     r31, Z
@@ -665,12 +675,104 @@ __tablejump2__:
        ijmp
 #else
        lpm
+       adiw    r30, 1
        push    r0
-       inc     r30     ; table is word aligned, no carry to high byte
        lpm
        push    r0
        ret
 #endif
-.endfunc
+       .endfunc
 #endif /* defined (L_tablejump) */
 
+/* __do_copy_data is only necessary if there is anything in .data section.
+   Does not use RAMPZ - crt*.o provides a replacement for >64K devices.  */
+
+#ifdef L_copy_data
+       .section .init4,"ax",@progbits
+       .global __do_copy_data
+__do_copy_data:
+       ldi     r17, hi8(__data_end)
+       ldi     r26, lo8(__data_start)
+       ldi     r27, hi8(__data_start)
+       ldi     r30, lo8(__data_load_start)
+       ldi     r31, hi8(__data_load_start)
+       rjmp    .do_copy_data_start
+.do_copy_data_loop:
+#if defined (__AVR_ENHANCED__)
+       lpm     r0, Z+
+#else
+       lpm
+       adiw    r30, 1
+#endif
+       st      X+, r0
+.do_copy_data_start:
+       cpi     r26, lo8(__data_end)
+       cpc     r27, r17
+       brne    .do_copy_data_loop
+#endif /* L_copy_data */
+
+/* __do_clear_bss is only necessary if there is anything in .bss section.  */
+
+#ifdef L_clear_bss
+       .section .init4,"ax",@progbits
+       .global __do_clear_bss
+__do_clear_bss:
+       ldi     r17, hi8(__bss_end)
+       ldi     r26, lo8(__bss_start)
+       ldi     r27, hi8(__bss_start)
+       rjmp    .do_clear_bss_start
+.do_clear_bss_loop:
+       st      X+, __zero_reg__
+.do_clear_bss_start:
+       cpi     r26, lo8(__bss_end)
+       cpc     r27, r17
+       brne    .do_clear_bss_loop
+#endif /* L_clear_bss */
+
+/* __do_global_ctors and __do_global_dtors are only necessary
+   if there are any constructors/destructors.  */
+
+#if defined (__AVR_MEGA__)
+#define XCALL call
+#else
+#define XCALL rcall
+#endif
+
+#ifdef L_ctors
+       .section .init6,"ax",@progbits
+       .global __do_global_ctors
+__do_global_ctors:
+       ldi     r17, hi8(__ctors_start)
+       ldi     r28, lo8(__ctors_end)
+       ldi     r29, hi8(__ctors_end)
+       rjmp    .do_global_ctors_start
+.do_global_ctors_loop:
+       sbiw    r28, 2
+       mov_h   r31, r29
+       mov_l   r30, r28
+       XCALL   __tablejump__
+.do_global_ctors_start:
+       cpi     r28, lo8(__ctors_start)
+       cpc     r29, r17
+       brne    .do_global_ctors_loop
+#endif /* L_ctors */
+
+#ifdef L_dtors
+       .section .fini6,"ax",@progbits
+       .global __do_global_dtors
+__do_global_dtors:
+       ldi     r17, hi8(__dtors_end)
+       ldi     r28, lo8(__dtors_start)
+       ldi     r29, hi8(__dtors_start)
+       rjmp    .do_global_dtors_start
+.do_global_dtors_loop:
+       mov_h   r31, r29
+       mov_l   r30, r28
+       XCALL   __tablejump__
+       adiw    r28, 2
+.do_global_dtors_start:
+       cpi     r28, lo8(__dtors_end)
+       cpc     r29, r17
+       brne    .do_global_dtors_loop
+#endif /* L_dtors */
+
index 0b28e8d..769085b 100644 (file)
@@ -17,7 +17,11 @@ LIB1ASMFUNCS = \
        _epilogue \
        _exit \
        _cleanup \
-       _tablejump
+       _tablejump \
+       _copy_data \
+       _clear_bss \
+       _ctors \
+       _dtors
 
 # We do not have the DF type.
 # Most of the C functions in libgcc2 use almost all registers,