From patchwork Thu Jan 4 16:28:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 1882540 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gjlay.de header.i=@gjlay.de header.a=rsa-sha256 header.s=strato-dkim-0002 header.b=kCnwKOJC; dkim=pass header.d=gjlay.de header.i=@gjlay.de header.a=ed25519-sha256 header.s=strato-dkim-0003 header.b=7vmJf5VT; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4T5X8Z5kDzz1ydd for ; Fri, 5 Jan 2024 03:28:46 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1A14D3857C60 for ; Thu, 4 Jan 2024 16:28:44 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de [85.215.255.22]) by sourceware.org (Postfix) with ESMTPS id A95B13858D33 for ; Thu, 4 Jan 2024 16:28:13 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A95B13858D33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=gjlay.de Authentication-Results: sourceware.org; spf=none smtp.mailfrom=gjlay.de ARC-Filter: OpenARC Filter v1.0.0 sourceware.org A95B13858D33 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=85.215.255.22 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1704385696; cv=pass; b=JtRRgynstOK8ahcypJOW3b+T24QuJEVIr6gr/NhbxpDopMOEnZMsAG7S1yesggw/am3fzYSx1b8LQLkFLEvPCw/ydqcgul3nQy4jaPq/mn6mqg8r3EXOXMUAgAyeQrQAMj5Nwo3ARdH+AKcdQGAhJNINI6N9YTToYL/DzM5hxpo= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1704385696; c=relaxed/simple; bh=zAErYjpbhxYkrBGqwHZ3AelnB374ew7uzxqNcvelQQI=; h=DKIM-Signature:DKIM-Signature:Message-ID:Date:MIME-Version:To: From:Subject; b=PEvChnlMP0UB3UHEC+FRtUVpClnFU1CvxIhge8KFwS9HK9ARnElCi42FBBGXzpQBDfNzsivLykAfbdzqPr0wblPCgxawpd2g5NLUtdQFiE8HXIukpUdKMvx/iduJn68Lj59jb9dKzFN5PaNGskM9woctvlML8vPkyJ+m+Tpk/3c= ARC-Authentication-Results: i=2; server2.sourceware.org ARC-Seal: i=1; a=rsa-sha256; t=1704385691; cv=none; d=strato.com; s=strato-dkim-0002; b=pFoouICMJgKALjVwrSIv/0d7gOvyBxt6vjaHrfjqPWImu9MUxlUMV34HQcKj0ML+mA joklDU+HHObeld4/qYAqr5YCmblkgVDv+yRxZ3Fcy6PJJKeik0UMg/w4aIPiPgDAROg7 UY9W91KfwP+TQgkK0ud7zV4sv8FiMaxO1htIu/fvt+Ws+eFmUnV9UrOZYySm4DXRXC/W IW1PuQ6YOUH65JA2gRQUT42EnWubST8F+eqEXJNft34a+o4zQzbksWyJWXE2E+hSCBjb b7lt9HLMPvB0HVwcsQLhoSkFgCygfsyB2WNuSpoxWUYnGKWg2LsceV7FQgZSPMjeb9NZ xO9A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1704385691; s=strato-dkim-0002; d=strato.com; h=Subject:From:To:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=RsUdm1MuagHgwZ05hw3KR6y6dlap+sui1R+KPSdZ7j0=; b=ZjWLKU9+z9f5m/frYn3zs6I0di83Q6jRYZloYstzcdmqp1YJctVCoUM5I1Nn7eRFin W77ba0hQK0o7q6f+jIO8jH7LZs3PmTglF4tCga8I1kFul1JPmhW+x95FKGd+wzsu8+PR nrxG0nrMV1HupQErFWjJjsR3vMwcTMh6hFRjsEZ298DqJflArHTMRrLZL1iqR03mezqZ InX+FltUPXeNaZPfkemhedLjmWvfGMYu/yV2GASTk2V0zjo/hLRGrxY0kfU9FZJObhz8 UzF83UkvrlRrQI184fN3+02wDrVIvv5Nd8ltS2moxsBUCFG9zf3zUYZ5tesuJbaFh1mL N/CA== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1704385691; s=strato-dkim-0002; d=gjlay.de; h=Subject:From:To:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=RsUdm1MuagHgwZ05hw3KR6y6dlap+sui1R+KPSdZ7j0=; b=kCnwKOJCmac4xwbwBLeyguJ8PnM0xJupR+VMU7olJ7dlyKMD7smpIfD1d6Hq1oBZvC z90N742Iz8rPqL2b3GDN52msIpG9FnWArZJiDw+L88FYWKnvbM0/bAGJ39KNONUF9LtV 0dTPcJop82eDA0nGKvYZ+QAwayMJT+6Cz7GyJKJPJgVfnpm4x105ZiLjKqp/Olnd0jhD tl33p/z2ObdwvBimeEopIieQeV9kjaWeLsYDC5z7bYO29Lcm5An08ijo8JLqmGYfpn+U 1JYt061C0zofTD9PJUhklDzwHvbrYiypwPxwoywHhmFVQlVOCfTxmjrzBKvHhapRYT++ SLig== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1704385691; s=strato-dkim-0003; d=gjlay.de; h=Subject:From:To:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=RsUdm1MuagHgwZ05hw3KR6y6dlap+sui1R+KPSdZ7j0=; b=7vmJf5VTaKy6oRJSZrO9/W3ra6OxQgX3OkwygqHJstZHK4vt/e4wysUIeUiab7V5X5 9Py0etRvl0N9GaOW7JDg== X-RZG-AUTH: ":LXoWVUeid/7A29J/hMvvT3koxZnKT7Qq0xotTetVnKkSjsSjo3O/MHXSz1aalw==" Received: from [192.168.2.102] by smtp.strato.de (RZmta 49.10.2 DYNA|AUTH) with ESMTPSA id 641e88004GSA9mh (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Thu, 4 Jan 2024 17:28:10 +0100 (CET) Message-ID: <83b90302-bd7b-4064-8c8e-7495ebd3931e@gjlay.de> Date: Thu, 4 Jan 2024 17:28:02 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: gcc-patches@gcc.gnu.org, Denis Chertykov From: Georg-Johann Lay Subject: [patch,avr,applied] PR target/112952 Fix attribute "io" et al. handling. X-Spam-Status: No, score=-9.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org 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. It also improves some diagnostics. Johann --- gcc/ PR target/112952 * config/avr/avr.cc (avr_handle_addr_attribute): Also print valid range when diagnosing attribute "io" and "io_low" are out of range. (avr_eval_addr_attrib): Don't ICE on empty address at that place. (avr_insert_attributes): Reject if attribute "address", "io" or "io_low" in contexts other than static storage. (avr_asm_output_aligned_decl_common): Move output of decls with attribute "address", "io", and "io_low" to... (avr_output_addr_attrib): ...this new function. (avr_asm_asm_output_aligned_bss): Remove output for decls with attribute "address", "io", and "io_low". (avr_encode_section_info): Rectify handling of decls with attribute "address", "io", and "io_low". gcc/testsuite/ PR target/112952 * gcc.target/avr/attribute-io.h: New file. * gcc.target/avr/pr112952-0.c: New test. * gcc.target/avr/pr112952-1.c: New test. * gcc.target/avr/pr112952-2.c: New test. * gcc.target/avr/pr112952-3.c: New test. diff --git a/gcc/testsuite/gcc.target/avr/attribute-io.h b/gcc/testsuite/gcc.target/avr/attribute-io.h new file mode 100644 index 00000000000..39abd4ef59f --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/attribute-io.h @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/avr/pr112952-0.c b/gcc/testsuite/gcc.target/avr/pr112952-0.c new file mode 100644 index 00000000000..1870bf3f702 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr112952-0.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/avr/pr112952-1.c b/gcc/testsuite/gcc.target/avr/pr112952-1.c new file mode 100644 index 00000000000..6e7d273c979 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr112952-1.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/avr/pr112952-2.c b/gcc/testsuite/gcc.target/avr/pr112952-2.c new file mode 100644 index 00000000000..0ef059804b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr112952-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/avr/pr112952-3.c b/gcc/testsuite/gcc.target/avr/pr112952-3.c new file mode 100644 index 00000000000..51da96761f7 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr112952-3.c @@ -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" } } */ diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index 224cb6c665f..7eb5d08653e 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -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