diff options
author | Marek Michalkiewicz <marekm@amelek.gda.pl> | 2002-06-02 01:33:47 +0200 |
---|---|---|
committer | Marek Michalkiewicz <marekm@gcc.gnu.org> | 2002-06-01 23:33:47 +0000 |
commit | 9af145ae9a5d597ed99ae4e836f653b8e9254759 (patch) | |
tree | aa46724eab46edd17324abbef5e7d558302464fb /gcc | |
parent | 0d66ad572b03eb9d8921c649ba6f4b0cfdf2e8b6 (diff) | |
download | gcc-9af145ae9a5d597ed99ae4e836f653b8e9254759.zip gcc-9af145ae9a5d597ed99ae4e836f653b8e9254759.tar.gz gcc-9af145ae9a5d597ed99ae4e836f653b8e9254759.tar.bz2 |
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.
From-SVN: r54156
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 44 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 21 | ||||
-rw-r--r-- | gcc/config/avr/libgcc.S | 112 | ||||
-rw-r--r-- | gcc/config/avr/t-avr | 6 |
5 files changed, 192 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f601740..391f551 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index cf7b6c0..61768018 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -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); +} + diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index 6102a03..d26bafd 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -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 diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S index d324a21..8548a73 100644 --- a/gcc/config/avr/libgcc.S +++ b/gcc/config/avr/libgcc.S @@ -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 */ + diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr index 0b28e8d..769085b 100644 --- a/gcc/config/avr/t-avr +++ b/gcc/config/avr/t-avr @@ -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, |