summaryrefslogtreecommitdiffstats
path: root/patches/gcc-4.4.3/atmel/0003-Fix-handling-of-empty-.data-or-.bss-section.patch
blob: f4a25552c2698e4f9752fd616fb55077452a6244 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
From 946c12c25ba51e81a019b52d9d74d170499a9586 Mon Sep 17 00:00:00 2001
From: Stephan Linz <linz@li-pro.net>
Date: Tue, 19 Apr 2011 22:52:41 +0200
Subject: [PATCH 03/10] Fix handling of empty .data or .bss section

Backend (avr part) lacks correct handling of empty .data or .bss
section and shouldn't emit __do_copy_data or __do_clear_bss in
such cases. This patch allows output these only if there is anything
in the .data or .bss sections. Some code size could be saved by not
linking in the initialization code from libgcc if one or both
sections are empty.

GCC bug #18145 report:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18145

Original ATMEL patch from:
http://distribute.atmel.no/tools/opensource/avr-gcc/gcc-4.4.3/41-gcc-4.4.3-bug-18145-v4.patch

Signed-off-by: Stephan Linz <linz@li-pro.net>
---
 gcc/config/avr/avr-protos.h |    3 +
 gcc/config/avr/avr.c        |   91 ++++++++++++++++++++++++++++++++++++++++---
 gcc/config/avr/avr.h        |   14 +-----
 3 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index c300c89..c832e39 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -39,6 +39,8 @@ extern int avr_simple_epilogue (void);
 extern void gas_output_limited_string (FILE *file, const char *str);
 extern void gas_output_ascii (FILE *file, const char *str, size_t length);
 extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
+extern void avr_asm_output_common (FILE *stream, const char *name, unsigned HOST_WIDE_INT size, unsigned HOST_WIDE_INT rounded);
+extern void avr_asm_output_local (FILE *stream, const char *name, unsigned HOST_WIDE_INT size, unsigned HOST_WIDE_INT rounded);
 
 #ifdef TREE_CODE
 extern void asm_output_external (FILE *file, tree decl, char *name);
@@ -126,6 +128,7 @@ extern RTX_CODE avr_normalize_condition (RTX_CODE condition);
 extern int compare_eq_p (rtx insn);
 extern void out_shift_with_cnt (const char *templ, rtx insn,
 				rtx operands[], int *len, int t_len);
+extern rtx avr_return_addr_rtx (int count, rtx tem);
 #endif /* RTX_CODE */
 
 #ifdef HAVE_MACHINE_MODES
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 4a2588d..a8aff30 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -76,6 +76,12 @@ static rtx avr_function_value (const_tree, const_tree, bool);
 static void avr_insert_attributes (tree, tree *);
 static void avr_asm_init_sections (void);
 static unsigned int avr_section_type_flags (tree, const char *, int);
+static void avr_asm_named_section (const char *name, unsigned int flags, tree decl);
+/* Track if code will use .bss and/or .data */
+static int avr_need_clear_bss_p = 0;
+static int avr_need_copy_data_p = 0;
+static void avr_output_data_section_asm_op (const void*);
+static void avr_output_bss_section_asm_op (const void*);
 
 static void avr_reorg (void);
 static void avr_asm_out_ctor (rtx, int);
@@ -5135,6 +5141,54 @@ avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
   fprintf (asm_out_file, "\t.p2align 1\n");
 }
 
+/* ASM_OUTPUT_COMMON */
+/* Track need of __do_clear_bss */
+
+void
+avr_asm_output_common (FILE *stream, const char *name,
+                       unsigned HOST_WIDE_INT size,
+                       unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
+{
+    avr_need_clear_bss_p = 1;
+    fputs ("\t.comm ", stream);
+    assemble_name (stream, name);
+    fprintf (stream, ",%lu,1\n", (unsigned long) size);
+}
+
+/* ASM_OUTPUT_LOCAL */
+/* Track need of __do_clear_bss */
+
+void
+avr_asm_output_local (FILE *stream, const char *name,
+                      unsigned HOST_WIDE_INT size,
+                      unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
+{
+    avr_need_clear_bss_p = 1;
+    fputs ("\t.lcomm ", stream);
+    assemble_name (stream, name);
+    fprintf (stream, ",%d\n", (int) size);
+}
+
+/* Unnamed section callback to track need of __do_copy_data */
+
+static void
+avr_output_data_section_asm_op (const void *data)
+{
+    avr_need_copy_data_p = 1;
+    /* Dispatch to default */
+    output_section_asm_op (data);
+}
+
+/* Unnamed section callback to track need of __do_clear_bss */
+
+static void
+avr_output_bss_section_asm_op (const void *data)
+{
+    avr_need_clear_bss_p = 1;
+    /* Dispatch to default */
+    output_section_asm_op (data);
+}
+
 /* Implement TARGET_ASM_INIT_SECTIONS.  */
 
 static void
@@ -5144,6 +5198,27 @@ avr_asm_init_sections (void)
 					 avr_output_progmem_section_asm_op,
 					 NULL);
   readonly_data_section = data_section;
+
+  data_section->unnamed.callback = avr_output_data_section_asm_op;
+  bss_section->unnamed.callback = avr_output_bss_section_asm_op;
+}
+
+/* TARGET_ASM_NAMED_SECTION */
+/* Track need of __do_clear_bss, __do_copy_data for named sections */
+
+static void
+avr_asm_named_section (const char *name, unsigned int flags, tree decl)
+{
+    if (!avr_need_copy_data_p)
+        avr_need_copy_data_p =
+            (0 == strncmp (name, ".data", 5)
+             || 0 == strncmp (name, ".rodata", 7)
+             || 0 == strncmp (name, ".gnu.linkonce.", 14));
+
+    if (!avr_need_clear_bss_p)
+        avr_need_clear_bss_p = (0 == strncmp (name, ".bss", 4));
+
+    default_elf_asm_named_section (name, flags, decl);
 }
 
 static unsigned int
@@ -5182,12 +5257,6 @@ avr_file_start (void)
   
   fputs ("__tmp_reg__ = 0\n" 
          "__zero_reg__ = 1\n", asm_out_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", asm_out_file);
-  fputs ("\t.global __do_clear_bss\n", asm_out_file);
 }
 
 /* Outputs to the stdio stream FILE some
@@ -5196,6 +5265,16 @@ avr_file_start (void)
 static void
 avr_file_end (void)
 {
+    /* Output these only if there is anything in the
+       .data* / .rodata* / .gnu.linkonce.* resp. .bss*
+       input section(s) - some code size can be saved by not
+       linking in the initialization code from libgcc if resp.
+       sections are empty. */
+    if (avr_need_copy_data_p)
+        fputs (".global __do_copy_data\n", asm_out_file);
+
+    if (avr_need_clear_bss_p)
+        fputs (".global __do_clear_bss\n", asm_out_file);
 }
 
 /* Choose the order in which to allocate hard registers for
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 54c607a..c0efa57 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -544,7 +544,7 @@ do {									    \
 #define ASM_APP_OFF "/* #NOAPP */\n"
 
 /* Switch into a generic section.  */
-#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
+#define TARGET_ASM_NAMED_SECTION avr_asm_named_section
 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
 
 #define ASM_OUTPUT_ASCII(FILE, P, SIZE)	 gas_output_ascii (FILE,P,SIZE)
@@ -552,21 +552,13 @@ do {									    \
 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C, STR) ((C) == '\n' || ((C) == '$'))
 
 #define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)			   \
-do {									   \
-     fputs ("\t.comm ", (STREAM));					   \
-     assemble_name ((STREAM), (NAME));					   \
-     fprintf ((STREAM), ",%lu,1\n", (unsigned long)(SIZE));		   \
-} while (0)
+        avr_asm_output_common (STREAM, NAME, SIZE, ROUNDED)
 
 #define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED)			\
   asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
 
 #define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED)			\
-do {									\
-     fputs ("\t.lcomm ", (STREAM));					\
-     assemble_name ((STREAM), (NAME));					\
-     fprintf ((STREAM), ",%d\n", (int)(SIZE));				\
-} while (0)
+        avr_asm_output_local (STREAM, NAME, SIZE, ROUNDED)
 
 #undef TYPE_ASM_OP
 #undef SIZE_ASM_OP
-- 
1.6.0.4