On Thu, 2024-01-04 17:28:02 +0100, Georg-Johann Lay <avr@gjlay.de> wrote:
> This fixes the avr-specific attributes io, io_low and address,
> that are all basically the same except that io and io_low imply
> assertions on allowed addressing modes.
> --- a/gcc/config/avr/avr.cc
> +++ b/gcc/config/avr/avr.cc
[...]
> @@ -10385,12 +10389,10 @@ avr_handle_addr_attribute (tree *node, tree name, tree args,
> }
> else if (io_p
> && (!tree_fits_shwi_p (arg)
> - || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
> - ? low_io_address_operand : io_address_operand)
> - (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
> + || ! IN_RANGE (TREE_INT_CST_LOW (arg), io_start, io_end)))
> {
> - warning_at (loc, OPT_Wattributes, "%qE attribute address "
> - "out of range", name);
> + warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
> + "range 0x%x...0x%x", name, (int) io_start, (int) io_end);
> *no_add = true;
> }
> else
Building with a recent GCC, this results in a new warning (here forced
to an error with --enable-werror-alway--enable-werror-always):
/var/lib/laminar/run/gcc-avr-elf/64/local-toolchain-install/bin/g++ -fno-PIE -c -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Wconditionally-supported -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror -fno-common -DHAVE_CONFIG_H -fno-PIE -I. -I. -I../../gcc/gcc -I../../gcc/gcc/. -I../../gcc/gcc/../include -I../../gcc/gcc/../libcpp/include -I../../gcc/gcc/../libcody -I../../gcc/gcc/../libdecnumber -I../../gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I../../gcc/gcc/../libbacktrace -o avr.o -MT avr.o -MMD -MP -MF ./.deps/avr.TPo ../../gcc/gcc/config/avr/avr.cc
../../gcc/gcc/config/avr/avr.cc: In function 'tree_node* avr_handle_addr_attribute(tree_node**, tree, tree, int, bool*)':
../../gcc/gcc/config/avr/avr.cc:10391:45: error: unquoted sequence of 3 consecutive punctuation characters '...' in format [-Werror=format-diag]
10391 | warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10392 | "range 0x%x...0x%x", name, (int) io_start, (int) io_end);
| ~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
make[1]: *** [Makefile:2554: avr.o] Error 1
make[1]: Leaving directory '/var/lib/laminar/run/gcc-avr-elf/64/toolchain-build/gcc'
make: *** [Makefile:4676: all-gcc] Error 2
I think this should be "%<...%>".
MfG, JBG
--
Am 12.01.24 um 04:37 schrieb Jan-Benedict Glaw:
> On Thu, 2024-01-04 17:28:02 +0100, Georg-Johann Lay <avr@gjlay.de> wrote:
>> This fixes the avr-specific attributes io, io_low and address,
>> that are all basically the same except that io and io_low imply
>> assertions on allowed addressing modes.
>
>> --- a/gcc/config/avr/avr.cc
>> +++ b/gcc/config/avr/avr.cc
> [...]
>> @@ -10385,12 +10389,10 @@ avr_handle_addr_attribute (tree *node, tree name, tree args,
>> }
>> else if (io_p
>> && (!tree_fits_shwi_p (arg)
>> - || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
>> - ? low_io_address_operand : io_address_operand)
>> - (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
>> + || ! IN_RANGE (TREE_INT_CST_LOW (arg), io_start, io_end)))
>> {
>> - warning_at (loc, OPT_Wattributes, "%qE attribute address "
>> - "out of range", name);
>> + warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
>> + "range 0x%x...0x%x", name, (int) io_start, (int) io_end);
>> *no_add = true;
>> }
>> else
>
> Building with a recent GCC, this results in a new warning (here forced
> to an error with --enable-werror-alway--enable-werror-always):
>
> /var/lib/laminar/run/gcc-avr-elf/64/local-toolchain-install/bin/g++ -fno-PIE -c -g -O2 -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Wconditionally-supported -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Werror -fno-common -DHAVE_CONFIG_H -fno-PIE -I. -I. -I../../gcc/gcc -I../../gcc/gcc/. -I../../gcc/gcc/../include -I../../gcc/gcc/../libcpp/include -I../../gcc/gcc/../libcody -I../../gcc/gcc/../libdecnumber -I../../gcc/gcc/../libdecnumber/dpd -I../libdecnumber -I../../gcc/gcc/../libbacktrace -o avr.o -MT avr.o -MMD -MP -MF ./.deps/avr.TPo ../../gcc/gcc/config/avr/avr.cc
> ../../gcc/gcc/config/avr/avr.cc: In function 'tree_node* avr_handle_addr_attribute(tree_node**, tree, tree, int, bool*)':
> ../../gcc/gcc/config/avr/avr.cc:10391:45: error: unquoted sequence of 3 consecutive punctuation characters '...' in format [-Werror=format-diag]
> 10391 | warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 10392 | "range 0x%x...0x%x", name, (int) io_start, (int) io_end);
> | ~~~~~~~~~~~~~~~~~~~
> cc1plus: all warnings being treated as errors
> make[1]: *** [Makefile:2554: avr.o] Error 1
> make[1]: Leaving directory '/var/lib/laminar/run/gcc-avr-elf/64/toolchain-build/gcc'
> make: *** [Makefile:4676: all-gcc] Error 2
>
>
> I think this should be "%<...%>".
>
> MfG, JBG
Hi,
thanks for sorting this out. I would install the patch below.
I must admit that I don't understand that warning and what is
illegal about having ellipses in a format string at that place.
That warning isn't even documented, at least as of 2024-02-12
https://gcc.gnu.org/onlinedocs/gcc/Option-Index.html
There should be no quotes around the ellipses, they are intended
as real ellipses.
Plus, I saw in other modules that it warns about format strings
like printf (";%i", 10); Why is ";" not allowed there?
Johann
--
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 0cdd035fa1a..4bc3cf929de 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -10388,8 +10388,8 @@ avr_handle_addr_attribute (tree *node, tree
name, tree args,
&& (!tree_fits_shwi_p (arg)
|| ! IN_RANGE (TREE_INT_CST_LOW (arg), io_start,
io_end)))
{
- warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
- "range 0x%x...0x%x", name, (int) io_start, (int)
io_end);
+ warning_at (loc, OPT_Wattributes, "%qE attribute address out
of range"
+ " 0x%x%s0x%x", name, (int) io_start, "...", (int)
io_end);
*no_add = true;
}
else
new file mode 100644
@@ -0,0 +1,74 @@
+/* { dg-do run } */
+/* { dg-options "-Os -save-temps" } */
+
+__attribute__((address(1234)))
+int g_1234;
+
+__attribute__((weak, address(4321)))
+int w_4321;
+
+__attribute__((address(5678)))
+static int l_5678;
+
+__attribute__((io_low(__AVR_SFR_OFFSET__ + 3)))
+volatile unsigned char g_low;
+
+__attribute__((weak, io_low(__AVR_SFR_OFFSET__ + 2)))
+volatile unsigned char w_low;
+
+__attribute__((io_low(__AVR_SFR_OFFSET__ + 1)))
+static volatile unsigned char l_low;
+
+__attribute__((io(__AVR_SFR_OFFSET__ + 35)))
+volatile unsigned char g_io;
+
+__attribute__((weak, io(__AVR_SFR_OFFSET__ + 34)))
+volatile unsigned char w_io;
+
+__attribute__((io(__AVR_SFR_OFFSET__ + 33)))
+static volatile unsigned char l_io;
+
+#define CMP(SYM, VAL) \
+ do { \
+ unsigned x; \
+ __asm ("" : "=d" (x) : "0" (& SYM)); \
+ if (x != VAL) \
+ __builtin_abort(); \
+ } while(0)
+
+
+int main (void)
+{
+ CMP (g_1234, 1234);
+ CMP (w_4321, 4321);
+ CMP (l_5678, 5678);
+
+ CMP (g_low, __AVR_SFR_OFFSET__ + 3);
+ CMP (w_low, __AVR_SFR_OFFSET__ + 2);
+ CMP (l_low, __AVR_SFR_OFFSET__ + 1);
+
+ CMP (g_io, __AVR_SFR_OFFSET__ + 35);
+ CMP (w_io, __AVR_SFR_OFFSET__ + 34);
+ CMP (l_io, __AVR_SFR_OFFSET__ + 33);
+
+ l_low = l_io;
+ g_low = g_io;
+ w_low = w_io;
+ l_low |= 1;
+ g_low |= 2;
+ w_low |= 4;
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler "g_1234 = 1234" } } */
+/* { dg-final { scan-assembler "w_4321 = 4321" } } */
+/* { dg-final { scan-assembler "l_5678 = 5678" } } */
+
+/* { dg-final { scan-assembler "\\.globl g_1234" } } */
+/* { dg-final { scan-assembler "\\.globl g_low" } } */
+/* { dg-final { scan-assembler "\\.globl g_io" } } */
+
+/* { dg-final { scan-assembler "\\.weak w_4321" } } */
+/* { dg-final { scan-assembler "\\.weak w_low" } } */
+/* { dg-final { scan-assembler "\\.weak w_io" } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-Os -save-temps -fno-data-sections -fno-common" } */
+
+#include "attribute-io.h"
+
+/* { dg-final { scan-assembler "g_1234 = 1234" } } */
+/* { dg-final { scan-assembler "w_4321 = 4321" } } */
+/* { dg-final { scan-assembler "l_5678 = 5678" } } */
+
+/* { dg-final { scan-assembler "\\.globl g_1234" } } */
+/* { dg-final { scan-assembler "\\.globl g_low" } } */
+/* { dg-final { scan-assembler "\\.globl g_io" } } */
+
+/* { dg-final { scan-assembler "\\.weak w_4321" } } */
+/* { dg-final { scan-assembler "\\.weak w_low" } } */
+/* { dg-final { scan-assembler "\\.weak w_io" } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-Os -save-temps -fno-data-sections -fcommon" } */
+
+#include "attribute-io.h"
+
+/* { dg-final { scan-assembler "g_1234 = 1234" } } */
+/* { dg-final { scan-assembler "w_4321 = 4321" } } */
+/* { dg-final { scan-assembler "l_5678 = 5678" } } */
+
+/* { dg-final { scan-assembler "\\.globl g_1234" } } */
+/* { dg-final { scan-assembler "\\.globl g_low" } } */
+/* { dg-final { scan-assembler "\\.globl g_io" } } */
+
+/* { dg-final { scan-assembler "\\.weak w_4321" } } */
+/* { dg-final { scan-assembler "\\.weak w_low" } } */
+/* { dg-final { scan-assembler "\\.weak w_io" } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-Os -save-temps -fdata-sections -fno-common" } */
+
+#include "attribute-io.h"
+
+/* { dg-final { scan-assembler "g_1234 = 1234" } } */
+/* { dg-final { scan-assembler "w_4321 = 4321" } } */
+/* { dg-final { scan-assembler "l_5678 = 5678" } } */
+
+/* { dg-final { scan-assembler "\\.globl g_1234" } } */
+/* { dg-final { scan-assembler "\\.globl g_low" } } */
+/* { dg-final { scan-assembler "\\.globl g_io" } } */
+
+/* { dg-final { scan-assembler "\\.weak w_4321" } } */
+/* { dg-final { scan-assembler "\\.weak w_low" } } */
+/* { dg-final { scan-assembler "\\.weak w_io" } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+/* { dg-options "-Os -save-temps -fdata-sections -fcommon" } */
+
+#include "attribute-io.h"
+
+/* { dg-final { scan-assembler "g_1234 = 1234" } } */
+/* { dg-final { scan-assembler "w_4321 = 4321" } } */
+/* { dg-final { scan-assembler "l_5678 = 5678" } } */
+
+/* { dg-final { scan-assembler "\\.globl g_1234" } } */
+/* { dg-final { scan-assembler "\\.globl g_low" } } */
+/* { dg-final { scan-assembler "\\.globl g_io" } } */
+
+/* { dg-final { scan-assembler "\\.weak w_4321" } } */
+/* { dg-final { scan-assembler "\\.weak w_low" } } */
+/* { dg-final { scan-assembler "\\.weak w_io" } } */
@@ -10362,6 +10362,10 @@ avr_handle_addr_attribute (tree *node, tree name, tree args,
int flags ATTRIBUTE_UNUSED, bool *no_add)
{
bool io_p = startswith (IDENTIFIER_POINTER (name), "io");
+ HOST_WIDE_INT io_start = avr_arch->sfr_offset;
+ HOST_WIDE_INT io_end = strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
+ ? io_start + 0x1f
+ : io_start + 0x3f;
location_t loc = DECL_SOURCE_LOCATION (*node);
if (!VAR_P (*node))
@@ -10385,12 +10389,10 @@ avr_handle_addr_attribute (tree *node, tree name, tree args,
}
else if (io_p
&& (!tree_fits_shwi_p (arg)
- || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
- ? low_io_address_operand : io_address_operand)
- (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
+ || ! IN_RANGE (TREE_INT_CST_LOW (arg), io_start, io_end)))
{
- warning_at (loc, OPT_Wattributes, "%qE attribute address "
- "out of range", name);
+ warning_at (loc, OPT_Wattributes, "%qE attribute address out of "
+ "range 0x%x...0x%x", name, (int) io_start, (int) io_end);
*no_add = true;
}
else
@@ -10433,7 +10435,6 @@ avr_eval_addr_attrib (rtx x)
attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
if (!attr || !TREE_VALUE (attr))
attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
- gcc_assert (attr);
}
if (!attr || !TREE_VALUE (attr))
attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
@@ -10689,6 +10690,16 @@ avr_pgm_check_var_decl (tree node)
static void
avr_insert_attributes (tree node, tree *attributes)
{
+ if (VAR_P (node)
+ && ! TREE_STATIC (node))
+ {
+ const char *names[] = { "io", "io_low", "address", NULL };
+ for (const char **p = names; *p; ++p)
+ if (lookup_attribute (*p, *attributes))
+ error ("variable %q+D with attribute %qs must be located in "
+ "static storage", node, *p);
+ }
+
avr_pgm_check_var_decl (node);
if (TARGET_MAIN_IS_OS_TASK
@@ -10792,37 +10803,11 @@ avr_rodata_in_flash_p ()
/* Track need of __do_clear_bss. */
void
-avr_asm_output_aligned_decl_common (FILE * stream,
- tree decl,
- const char *name,
- unsigned HOST_WIDE_INT size,
- unsigned int align, bool local_p)
+avr_asm_output_aligned_decl_common (FILE *stream, tree /* decl */,
+ const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned int align, bool local_p)
{
- rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
- rtx symbol;
-
- if (mem != NULL_RTX && MEM_P (mem)
- && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
- && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
- {
- if (!local_p)
- {
- fprintf (stream, "\t.globl\t");
- assemble_name (stream, name);
- fprintf (stream, "\n");
- }
- if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
- {
- assemble_name (stream, name);
- fprintf (stream, " = %ld\n",
- (long) INTVAL (avr_eval_addr_attrib (symbol)));
- }
- else if (local_p)
- error_at (DECL_SOURCE_LOCATION (decl),
- "static IO declaration for %q+D needs an address", decl);
- return;
- }
-
/* __gnu_lto_slim is just a marker for the linker injected by toplev.cc.
There is no need to trigger __do_clear_bss code for them. */
@@ -10835,6 +10820,9 @@ avr_asm_output_aligned_decl_common (FILE * stream,
ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
}
+
+/* Implement `ASM_OUTPUT_ALIGNED_BSS'. */
+
void
avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
unsigned HOST_WIDE_INT size, int align,
@@ -10842,20 +10830,10 @@ avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
(FILE *, tree, const char *,
unsigned HOST_WIDE_INT, int))
{
- rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
- rtx symbol;
+ if (!startswith (name, "__gnu_lto"))
+ avr_need_clear_bss_p = true;
- if (mem != NULL_RTX && MEM_P (mem)
- && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
- && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
- {
- if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
- error_at (DECL_SOURCE_LOCATION (decl),
- "IO definition for %q+D needs an address", decl);
- avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
- }
- else
- default_func (file, decl, name, size, align);
+ default_func (file, decl, name, size, align);
}
@@ -10894,6 +10872,58 @@ avr_output_progmem_section_asm_op (const char *data)
}
+/* A noswitch section callback to output symbol definitions for
+ attributes "io", "io_low" and "address". */
+
+static bool
+avr_output_addr_attrib (tree decl, const char *name,
+ unsigned HOST_WIDE_INT /* size */,
+ unsigned HOST_WIDE_INT /* align */)
+{
+ gcc_assert (DECL_RTL_SET_P (decl));
+
+ FILE *stream = asm_out_file;
+ bool local_p = ! DECL_WEAK (decl) && ! TREE_PUBLIC (decl);
+ rtx symbol, mem = DECL_RTL (decl);
+
+ if (mem != NULL_RTX && MEM_P (mem)
+ && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
+ && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
+ {
+ if (! local_p)
+ {
+ fprintf (stream, "\t%s\t", DECL_WEAK (decl) ? ".weak" : ".globl");
+ assemble_name (stream, name);
+ fprintf (stream, "\n");
+ }
+
+ if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
+ {
+ assemble_name (stream, name);
+ fprintf (stream, " = %ld\n",
+ (long) INTVAL (avr_eval_addr_attrib (symbol)));
+ }
+ else if (local_p)
+ {
+ const char *names[] = { "io", "io_low", "address", NULL };
+ for (const char **p = names; *p; ++p)
+ if (lookup_attribute (*p, DECL_ATTRIBUTES (decl)))
+ {
+ error ("static attribute %qs declaration for %q+D needs an "
+ "address", *p, decl);
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ gcc_unreachable();
+
+ return false;
+}
+
+
/* Implement `TARGET_ASM_INIT_SECTIONS'. */
static void
@@ -10907,6 +10937,7 @@ avr_asm_init_sections (void)
readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
data_section->unnamed.callback = avr_output_data_section_asm_op;
bss_section->unnamed.callback = avr_output_bss_section_asm_op;
+ tls_comm_section->noswitch.callback = avr_output_addr_attrib;
}
@@ -11085,15 +11116,17 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
tree io_low_attr = lookup_attribute ("io_low", attr);
tree io_attr = lookup_attribute ("io", attr);
+ tree address_attr = lookup_attribute ("address", attr);
if (io_low_attr
&& TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
- addr_attr = io_attr;
+ addr_attr = io_low_attr;
else if (io_attr
&& TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
addr_attr = io_attr;
else
- addr_attr = lookup_attribute ("address", attr);
+ addr_attr = address_attr;
+
if (io_low_attr
|| (io_attr && addr_attr
&& low_io_address_operand
@@ -11108,6 +11141,36 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
don't use the exact value for constant propagation. */
if (addr_attr && !DECL_EXTERNAL (decl))
SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
+
+ if (io_attr || io_low_attr || address_attr)
+ {
+ if (DECL_INITIAL (decl))
+ {
+ /* Initializers are not yet parsed in TARGET_INSERT_ATTRIBUTES,
+ hence deny initializers now. The values of symbols with an
+ address attribute are determined by the attribute, not by
+ some initializer. */
+
+ error ("variable %q+D with attribute %qs must not have an "
+ "initializer", decl,
+ io_low_attr ? "io_low" : io_attr ? "io" : "address");
+ }
+ else
+ {
+ /* PR112952: The only way to output a variable declaration in a
+ custom manner is by means of a noswitch section callback.
+ There are only three noswitch sections: comm_section,
+ lcomm_section and tls_comm_section. And there is no way to
+ wire a custom noswitch section to a decl. As lcomm_section
+ is bypassed with -fdata-sections -fno-common, there is no
+ other way than making use of tls_comm_section. As we are
+ using that section anyway, also use it in the public case. */
+
+ DECL_COMMON (decl) = 1;
+ set_decl_section_name (decl, (const char*) nullptr);
+ set_decl_tls_model (decl, (tls_model) 2);
+ }
+ }
}
if (AVR_TINY