From patchwork Sat Nov 13 20:37:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 47625 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7DD223858036 for ; Sat, 13 Nov 2021 20:44:08 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7DD223858036 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636836248; bh=utpELLBw6zIdKS8Xid+GF2AjZ/D1ffZFR03BckoFMXc=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=pZ8GtDkgf/lVHdhqogIo6g8B61XlTFUaUVtJIpbGMi3BC0kAKXMG/lZrEtT4od11L EgwvksZCylxBtD9biIvApYlAxVbvztgyKbHQrBdlYTc52ls+0d4+jh2nBDutbSfPez skxUIbf+K06CMWrDKkmTOzNjkk51VqdSslhXF/eE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTPS id C1FB73858427 for ; Sat, 13 Nov 2021 20:37:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C1FB73858427 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-585-mURcqNzJOOSSNdZp-LnTXQ-1; Sat, 13 Nov 2021 15:37:41 -0500 X-MC-Unique: mURcqNzJOOSSNdZp-LnTXQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2F4201006AA0; Sat, 13 Nov 2021 20:37:40 +0000 (UTC) Received: from t14s.localdomain.com (ovpn-113-54.phx2.redhat.com [10.3.113.54]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D70119D9D; Sat, 13 Nov 2021 20:37:39 +0000 (UTC) To: gcc-patches@gcc.gnu.org, linux-toolchains@vger.kernel.org Subject: [PATCH 1a/6] RFC: Implement "#pragma GCC custom_address_space" Date: Sat, 13 Nov 2021 15:37:25 -0500 Message-Id: <20211113203732.2098220-2-dmalcolm@redhat.com> In-Reply-To: <20211113203732.2098220-1-dmalcolm@redhat.com> References: <20211113203732.2098220-1-dmalcolm@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-53.3 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: David Malcolm via Gcc-patches From: David Malcolm Reply-To: David Malcolm Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This work-in-progress patch adds a new: #prgama GCC custom_address_space(NAME_OF_ADDRESS_SPACE) for use by the C front-end. Currently the custom address spaces are: - disjoint from all other address spaces, *including* the generic one - treated the same as the generic address space at the RTL level (in terms of code generation) - treated as "untrusted" by -fanalyzer in a follow-up patch. but additional syntax could be added to change those defaults if needed. The intended use for this is in Linux kernel code, allowing e.g.: #define __kernel #pragma GCC custom_address_space(__user) #pragma GCC custom_address_space(__iomem) #pragma GCC custom_address_space(__percpu) #pragma GCC custom_address_space(__rcu) so that the C front-end can complain about mismatching user-space vs kernel-space pointers during type-checking (and that -fanalyzer can detect infoleaks and "taint" as data is copied across trust boundaries). Known issues: - addr_space_convert is not implemented. - there isn't yet a way to forcibly cast between address spaces, perhaps this should be a built-in function. - only tested so far on x86_64 (probably needs to use ensure_builtin_addr_space everywhere in the target-specific code that tests against specific address space IDs). - issue in testsuite (custom-address-space-2.c) - issue with precompiled headers gcc/ChangeLog: * Makefile.in (OBJS): Add addr-space.o. (GTFILES): Add addr-space.cc. * addr-space.cc: New file. * addr-space.h: New file. * auto-inc-dec.c: Include "addr-space.h". (find_inc): Convert targetm.addr_space. uses into addr_space_ calls. * builtins.c: Include "addr-space.h". (get_builtin_sync_mem): Convert targetm.addr_space. use into addr_space_ call. * cfgexpand.c: Include "addr-space.h". (convert_debug_memory_address): Convert targetm.addr_space. uses into addr_space_ calls. (expand_debug_expr): Likewise. * config/i386/i386.c: Include "addr-space.h". (ix86_print_operand_address_as): Call ensure_builtin_addr_space. * coretypes.h (ADDR_SPACE_T_MAX): New. (struct custom_addr_space): New forward decl. * doc/extend.texi (Named Address Spaces): Mention the new pragma. (Custom Address Space Pragmas): New node and subsection. * dwarf2out.c: Include "addr-space.h". (modified_type_die): Convert targetm.addr_space. use into addr_space_ call. * emit-rtl.c: Include "addr-space.h". (adjust_address_1): Convert targetm.addr_space. use into addr_space_ call. * explow.c: Include "addr-space.h". (convert_memory_address_addr_space_1): Convert targetm.addr_space. use into addr_space_ call. (memory_address_addr_space): Likewise. (promote_mode): Likewise. * expr.c: Include "addr-space.h". (store_expr): Convert targetm.addr_space. use into addr_space_ call. (expand_expr_addr_expr): Likewise. (expand_expr_real_2): Likewise. (expand_expr_real_1): Likewise. * fold-const.c: Include "addr-space.h". (const_unop): Convert targetm.addr_space. use into addr_space_ call. * gimple.c: Include "addr-space.h". (check_loadstore): Convert targetm.addr_space. use into addr_space_ call. * lra-constraints.c: Include "addr-space.h". (valid_address_p): Convert targetm.addr_space. use into addr_space_ call. * pointer-query.cc: Include "addr-space.h"; drop include of "target.h". (compute_objsize_r): Convert targetm.addr_space. use into addr_space_ call. * recog.c: Include "addr-space.h". (memory_address_addr_space_p): Convert targetm.addr_space. use into addr_space_ call. (offsettable_address_addr_space_p): Likewise. * reload.c: Include "addr-space.h". (strict_memory_address_addr_space_p): Convert targetm.addr_space. use into addr_space_ call. (find_reloads_address): Likewise. * rtlanal.c: Include "addr-space.h". (get_address_mode): Convert targetm.addr_space. use into addr_space_ call. * tree-ssa-address.c: Include "addr-space.h". (addr_for_mem_ref): Convert targetm.addr_space. use into addr_space_ call. (multiplier_allowed_in_address_p): Likewise. (most_expensive_mult_to_index): Likewise. * tree-ssa-loop-ivopts.c: Include "addr-space.h". (addr_offset_valid_p): Convert targetm.addr_space. use into addr_space_ call. (produce_memory_decl_rtl): Likewise. * tree.c: Include "addr-space.h". (build_pointer_type_for_mode): Convert targetm.addr_space. use into addr_space_ call. (build_reference_type_for_mode): Likewise. * varasm.c: Include "addr-space.h". (make_decl_rtl): Convert targetm.addr_space. use into addr_space_ call. (output_constant): Likewise. gcc/c-family/ChangeLog: * c-attribs.c: Include "addr-space.h". (handle_mode_attribute): Convert targetm.addr_space. use into addr_space_ call. * c-common.h (c_register_custom_addr_space): New decl. * c-pragma.c: Include "addr-space.h". (handle_pragma_custom_address_space): New. (init_pragma): Register the new pragma "GCC custom_address_space". Create the address space manager. gcc/c/ChangeLog: * c-decl.c: Include "addr-space.h". (c_build_pointer_type): Convert targetm.addr_space. use into addr_space_ call. (register_addr_space_identifier): New, split out from... (c_register_addr_space): ...this function. (c_register_custom_addr_space): New. * c-parser.c: Include "addr-space.h". (c_lex_one_token): Convert targetm.addr_space. use into addr_space_ call. * c-typeck.c: Include "addr-space.h". (addr_space_superset): Convert targetm.addr_space. uses into addr_space_ calls. (build_c_cast): Quote the names of named address spaces. (convert_for_assignment): Convert targetm.addr_space. use into addr_space_ call. Add auto_diagnostic_group and a note about which types were involved when complaining about mismatching address spaces. gcc/cp/ChangeLog: * tree.c (c_register_custom_addr_space): New stub. gcc/testsuite/ChangeLog: * gcc.dg/custom-address-space-1.c: New test. * gcc.dg/custom-address-space-2.c: New test. * gcc.dg/custom-address-space-3.c: New test. Signed-off-by: David Malcolm --- gcc/Makefile.in | 2 + gcc/addr-space.cc | 177 ++++++++++++++++++ gcc/addr-space.h | 122 ++++++++++++ gcc/auto-inc-dec.c | 5 +- gcc/builtins.c | 3 +- gcc/c-family/c-attribs.c | 3 +- gcc/c-family/c-common.h | 1 + gcc/c-family/c-pragma.c | 30 +++ gcc/c/c-decl.c | 59 +++++- gcc/c/c-parser.c | 3 +- gcc/c/c-typeck.c | 34 ++-- gcc/cfgexpand.c | 9 +- gcc/config/i386/i386.c | 3 + gcc/coretypes.h | 3 + gcc/cp/tree.c | 8 + gcc/doc/extend.texi | 46 +++++ gcc/dwarf2out.c | 3 +- gcc/emit-rtl.c | 3 +- gcc/explow.c | 11 +- gcc/expr.c | 17 +- gcc/fold-const.c | 3 +- gcc/gimple.c | 3 +- gcc/lra-constraints.c | 3 +- gcc/pointer-query.cc | 4 +- gcc/recog.c | 7 +- gcc/reload.c | 5 +- gcc/rtlanal.c | 3 +- gcc/testsuite/gcc.dg/custom-address-space-1.c | 174 +++++++++++++++++ gcc/testsuite/gcc.dg/custom-address-space-2.c | 21 +++ gcc/testsuite/gcc.dg/custom-address-space-3.c | 15 ++ gcc/tree-ssa-address.c | 9 +- gcc/tree-ssa-loop-ivopts.c | 5 +- gcc/tree.c | 5 +- gcc/varasm.c | 7 +- 34 files changed, 742 insertions(+), 64 deletions(-) create mode 100644 gcc/addr-space.cc create mode 100644 gcc/addr-space.h create mode 100644 gcc/testsuite/gcc.dg/custom-address-space-1.c create mode 100644 gcc/testsuite/gcc.dg/custom-address-space-2.c create mode 100644 gcc/testsuite/gcc.dg/custom-address-space-3.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 571e9c28e29..846f44f24fa 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1296,6 +1296,7 @@ OBJS = \ insn-recog.o \ insn-enums.o \ ggc-page.o \ + addr-space.o \ adjust-alignment.o \ alias.o \ alloc-pool.o \ @@ -2655,6 +2656,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/symtab-thunks.h $(srcdir)/symtab-thunks.cc \ $(srcdir)/symtab-clones.h \ $(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \ + $(srcdir)/addr-space.cc \ $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \ $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-utils.h \ $(srcdir)/ipa-param-manipulation.h $(srcdir)/ipa-sra.c $(srcdir)/dbxout.c \ diff --git a/gcc/addr-space.cc b/gcc/addr-space.cc new file mode 100644 index 00000000000..ebb2829171f --- /dev/null +++ b/gcc/addr-space.cc @@ -0,0 +1,177 @@ +/* Support for managing address spaces (both target-specific and custom). + Copyright (C) 2021 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "addr-space.h" +#include "target.h" + +/* If AS is a custom address space, return a built-in address space + that's equivalent to it at the RTL level. + Otherwise, return AS. */ + +addr_space_t +ensure_builtin_addr_space (addr_space_t as) +{ + /* For now, map all custom address spaces to the generic address space. */ + if (g_addr_space_mgr) + if (g_addr_space_mgr->custom_p (as)) + return ADDR_SPACE_GENERIC; + return as; +} + +/* Various functions to act on addr_space_t. + These handle custom address spaces, and otherwise call into the + corresponding target hook targetm.addr_space.NAME. */ + +scalar_int_mode +addr_space_pointer_mode (addr_space_t address_space) +{ + address_space = ensure_builtin_addr_space (address_space); + return targetm.addr_space.pointer_mode (address_space); +} + +scalar_int_mode +addr_space_address_mode (addr_space_t address_space) +{ + address_space = ensure_builtin_addr_space (address_space); + return targetm.addr_space.address_mode (address_space); +} + +bool +addr_space_valid_pointer_mode (scalar_int_mode mode, + addr_space_t as) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.valid_pointer_mode (mode, as); +} + +bool +addr_space_legitimate_address_p (machine_mode mode, rtx exp, + bool strict, addr_space_t as) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.legitimate_address_p (mode, exp, strict, as); +} + +rtx +addr_space_legitimize_address (rtx x, rtx oldx, machine_mode mode, + addr_space_t as) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.legitimize_address (x, oldx, mode, as); +} + +bool +addr_space_subset_p (addr_space_t subset, addr_space_t superset) +{ + if (subset == superset) + return true; + if (g_addr_space_mgr) + { + /* For now, assume all custom address spaces are disjoint + from each other and from builtin address spaces. */ + if (g_addr_space_mgr->custom_p (subset) + || g_addr_space_mgr->custom_p (superset)) + return false; + } + /* We have a pair of target-defined implicit address spaces. */ + return targetm.addr_space.subset_p (subset, superset); +} + +bool +addr_space_zero_address_valid (addr_space_t as) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.zero_address_valid (as); +} + +rtx +addr_space_convert (rtx /*op*/, tree /*from_type*/, tree /*to_type*/) +{ + gcc_unreachable (); // TODO +} + +int +addr_space_debug (addr_space_t as) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.debug (as); +} + +void +addr_space_diagnose_usage (addr_space_t as, location_t loc) +{ + as = ensure_builtin_addr_space (as); + return targetm.addr_space.diagnose_usage (as, loc); +} + +/* class addr_space_manager. */ + +addr_space_manager::addr_space_manager () +: m_custom_addr_spaces (NULL), + m_max_static_addr_space (0), + m_last_addr_space (0) +{ +} + +/* Hook to be called when a built-in address space is registered. */ + +void +addr_space_manager::on_builtin_addr_space (addr_space_t as) +{ + /* All builtin addr spaces should have been created before creating + any custom address spaces. */ + gcc_assert (m_custom_addr_spaces == NULL); + + m_max_static_addr_space = MAX (m_max_static_addr_space, as); + m_last_addr_space = m_max_static_addr_space; +} + +/* Attempt to populate *OUT with a previously unused value. + Return true if successful, false otherwise. */ + +bool +addr_space_manager::assign_dynamic_addr_space_t (addr_space_t *out) +{ + if (m_last_addr_space == ADDR_SPACE_T_MAX) + return false; + + *out = ++m_last_addr_space; + return true; +} + +/* Create a new custom_addr_space in the GC heap and stash a pointer to it. */ + +custom_addr_space * +addr_space_manager::create_custom_addr_space (tree name, + addr_space_t as, + location_t loc) +{ + custom_addr_space *result + = new (ggc_alloc ()) custom_addr_space (name, as, loc); + vec_safe_push (m_custom_addr_spaces, result); + return result; +} + +/* The singleton instance of addr_space_manager. */ + +addr_space_manager *g_addr_space_mgr; diff --git a/gcc/addr-space.h b/gcc/addr-space.h new file mode 100644 index 00000000000..3da9a70c5d7 --- /dev/null +++ b/gcc/addr-space.h @@ -0,0 +1,122 @@ +/* Support for managing address spaces (both target-specific and custom). + Copyright (C) 2021 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#ifndef GCC_ADDR_SPACE_H +#define GCC_ADDR_SPACE_H + +extern addr_space_t ensure_builtin_addr_space (addr_space_t as); + +/* Various functions to act on addr_space_t. + These handle custom address spaces, and otherwise call into the + corresponding target hook targetm.addr_space.NAME. */ + +/* MODE to use for a pointer into another address space. */ +extern scalar_int_mode addr_space_pointer_mode (addr_space_t address_space); + +/* MODE to use for an address in another address space. */ +extern scalar_int_mode addr_space_address_mode (addr_space_t address_space); + +/* True if MODE is valid for a pointer in __attribute__((mode("MODE"))) + in another address space. */ +extern bool addr_space_valid_pointer_mode (scalar_int_mode mode, + addr_space_t as); + +/* True if an address is a valid memory address to a given named address + space for a given mode. */ +extern bool addr_space_legitimate_address_p (machine_mode mode, rtx exp, + bool strict, addr_space_t as); + +/* Return an updated address to convert an invalid pointer to a named + address space to a valid one. If NULL_RTX is returned use machine + independent methods to make the address valid. */ +extern rtx addr_space_legitimize_address (rtx x, rtx oldx, machine_mode mode, + addr_space_t as); + +/* True if one named address space is a subset of another named address. */ +extern bool addr_space_subset_p (addr_space_t subset, addr_space_t superset); + +/* True if 0 is a valid address in the address space, or false if + 0 is a NULL in the address space. */ +extern bool addr_space_zero_address_valid (addr_space_t as); + +/* Function to convert an rtl expression from one address space to another. */ +extern rtx addr_space_convert (rtx op, tree from_type, tree to_type); + +/* Function to encode an address space into dwarf. */ +extern int addr_space_debug (addr_space_t as); + +/* Function to emit custom diagnostic if an address space is used. */ +extern void addr_space_diagnose_usage (addr_space_t as, location_t loc); + + +/* Data structures for managing custom address spaces. */ + +/* These are GC-managed so that custom address spaces are preserved in + PCH files. */ + +/* A custom address space. */ + +struct GTY(()) custom_addr_space +{ + custom_addr_space () {} + custom_addr_space (tree id, addr_space_t as, location_t pragma_loc) + : m_id (id), m_as (as), m_pragma_loc (pragma_loc) + { + } + + tree m_id; + addr_space_t m_as; + /* The location of the #pragma declaring this object. */ + location_t m_pragma_loc; + + /* TODO: additional properties of the address space. */ +}; + +/* A class to manage addr_space_t IDs and custom_addr_space instances. + + Targets have statically-assigned address space IDs, which are used + e.g. as cases in switch statements so we need to do a two-phase + allocation: all statically-assigned addr_space_t IDs, then any + dynamically-assigned addr_space_t IDs. */ + +class GTY(()) addr_space_manager +{ + public: + addr_space_manager (); + void on_builtin_addr_space (addr_space_t); + bool assign_dynamic_addr_space_t (addr_space_t *out); + custom_addr_space *create_custom_addr_space (tree name, + addr_space_t as, + location_t loc); + bool custom_p (addr_space_t as) const + { + return as > m_max_static_addr_space; + } + + private: + vec *m_custom_addr_spaces; + addr_space_t m_max_static_addr_space; + addr_space_t m_last_addr_space; +}; + +extern GTY(()) addr_space_manager *g_addr_space_mgr; + +/* TODO: test coverage for PCH. */ + +#endif /* GCC_ADDR_SPACE_H */ diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c index c531df8815c..04c7480c520 100644 --- a/gcc/auto-inc-dec.c +++ b/gcc/auto-inc-dec.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "dbgcnt.h" #include "print-rtl.h" #include "valtrack.h" +#include "addr-space.h" /* This pass was originally removed from flow.c. However there is almost nothing that remains of that code. @@ -1172,7 +1173,7 @@ find_inc (bool first_try) the inc must be a valid addressing reg. */ addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc); if (GET_MODE (inc_insn.reg_res) - != targetm.addr_space.address_mode (as)) + != addr_space_address_mode (as)) { if (dump_file) fprintf (dump_file, "base reg mode failure.\n"); @@ -1223,7 +1224,7 @@ find_inc (bool first_try) must be a valid addressing reg. */ addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc); if (GET_MODE (inc_insn.reg_res) - != targetm.addr_space.address_mode (as)) + != addr_space_address_mode (as)) { if (dump_file) fprintf (dump_file, "base reg mode failure.\n"); diff --git a/gcc/builtins.c b/gcc/builtins.c index 384864bfb3a..213785703fd 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see #include "demangle.h" #include "gimple-range.h" #include "pointer-query.h" +#include "addr-space.h" struct target_builtins default_target_builtins; #if SWITCHABLE_TARGET @@ -5562,7 +5563,7 @@ get_builtin_sync_mem (tree loc, machine_mode mode) int addr_space = TYPE_ADDR_SPACE (POINTER_TYPE_P (TREE_TYPE (loc)) ? TREE_TYPE (TREE_TYPE (loc)) : TREE_TYPE (loc)); - scalar_int_mode addr_mode = targetm.addr_space.address_mode (addr_space); + scalar_int_mode addr_mode = addr_space_address_mode (addr_space); addr = expand_expr (loc, NULL_RTX, addr_mode, EXPAND_SUM); addr = convert_memory_address (addr_mode, addr); diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 007b928c54b..e957d620651 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "tree-pretty-print.h" #include "gcc-rich-location.h" +#include "addr-space.h" static tree handle_packed_attribute (tree *, tree, tree, int, bool *); static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *); @@ -2115,7 +2116,7 @@ handle_mode_attribute (tree *node, tree name, tree args, tree (*fn)(tree, machine_mode, bool); if (!is_a (mode, &addr_mode) - || !targetm.addr_space.valid_pointer_mode (addr_mode, as)) + || !addr_space_valid_pointer_mode (addr_mode, as)) { error ("invalid pointer mode %qs", p); return NULL_TREE; diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index d5dad99ff97..d9d5cc35a4c 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -831,6 +831,7 @@ extern tree (*make_fname_decl) (location_t, tree, int); /* In c-decl.c and cp/tree.c. FIXME. */ extern void c_register_addr_space (const char *str, addr_space_t as); +extern custom_addr_space *c_register_custom_addr_space (tree id, location_t loc); /* In c-common.c. */ extern bool in_late_binary_op; diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 3663eb1cfbb..d4c57fb5544 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "plugin.h" #include "opt-suggestions.h" +#include "addr-space.h" #define GCC_BAD(gmsgid) \ do { warning (OPT_Wpragmas, gmsgid); return; } while (0) @@ -1220,6 +1221,30 @@ handle_pragma_message (cpp_reader *ARG_UNUSED(dummy)) TREE_STRING_POINTER (message)); } +/* Handle #pragma GCC custom_address_space by attempting to register a + custom address space. */ + +static void +handle_pragma_custom_address_space (cpp_reader *) +{ + location_t loc, id_loc; + tree x; + tree id; + const char *name = "#pragma GCC custom_address_space"; + if (pragma_lex (&x, &loc) != CPP_OPEN_PAREN) + GCC_BAD2_AT (loc, "missing %<(%> after %<%s%> - ignored", name); + + if (pragma_lex (&id, &id_loc) != CPP_NAME) + GCC_BAD2_AT (id_loc, + "expected an identifier after %<%s(%> - ignored", name); + + if (pragma_lex (&x) != CPP_CLOSE_PAREN) + GCC_BAD2_AT (loc, "malformed %<%s%> - ignored", name); + + c_register_custom_addr_space (id, id_loc); + /* FIXME: additional clauses to set properties of addr space? */ +} + /* Mark whether the current location is valid for a STDC pragma. */ static bool valid_location_for_stdc_pragma; @@ -1643,6 +1668,11 @@ init_pragma (void) c_register_pragma_with_expansion (0, "message", handle_pragma_message); + c_register_pragma ("GCC", "custom_address_space", + handle_pragma_custom_address_space); + gcc_assert (g_addr_space_mgr == NULL); + g_addr_space_mgr + = new (ggc_alloc ()) addr_space_manager (); #ifdef REGISTER_TARGET_PRAGMAS REGISTER_TARGET_PRAGMAS (); #endif diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 186fa1692c1..c670f12ae06 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "context.h" /* For 'g'. */ #include "omp-general.h" #include "omp-offload.h" /* For offload_vars. */ +#include "addr-space.h" #include "tree-pretty-print.h" @@ -653,7 +654,7 @@ c_build_pointer_type (tree to_type) machine_mode pointer_mode; if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode) - pointer_mode = targetm.addr_space.pointer_mode (as); + pointer_mode = addr_space_pointer_mode (as); else pointer_mode = c_default_pointer_mode; return build_pointer_type_for_mode (to_type, pointer_mode, false); @@ -12334,23 +12335,67 @@ c_parse_final_cleanups (void) ext_block = NULL; } +/* Register ID as a reserved word for the given RID. */ + +static void +register_addr_space_identifier (tree id, int rid) +{ + C_SET_RID_CODE (id, rid); + C_IS_RESERVED_WORD (id) = 1; + ridpointers [rid] = id; +} + /* Register reserved keyword WORD as qualifier for address space AS. */ void c_register_addr_space (const char *word, addr_space_t as) { + /* Address space qualifiers are only supported + in C with GNU extensions enabled. */ + if (c_dialect_objc () || flag_no_asm) + return; + + tree id = get_identifier (word); + int rid = RID_FIRST_ADDR_SPACE + as; - tree id; + register_addr_space_identifier (id, rid); + gcc_assert (g_addr_space_mgr); + g_addr_space_mgr->on_builtin_addr_space (as); +} + +/* Attempt to register a custom address space, reserving ID at LOC for + it as a reserved word. + If successful, register a GC-allocated custom_addr_space, registered + with the address_space_manager. + Otherwise emit a diagnostic and return NULL. */ + +custom_addr_space * +c_register_custom_addr_space (tree id, location_t loc) +{ /* Address space qualifiers are only supported in C with GNU extensions enabled. */ if (c_dialect_objc () || flag_no_asm) - return; + return NULL; // FIXME: diagnostic - id = get_identifier (word); - C_SET_RID_CODE (id, rid); - C_IS_RESERVED_WORD (id) = 1; - ridpointers [rid] = id; + gcc_assert (g_addr_space_mgr); + + addr_space_t as; + if (!g_addr_space_mgr->assign_dynamic_addr_space_t (&as)) + { + warning_at (loc, OPT_Wpragmas, "too many custom address spaces"); + return NULL; + } + + int rid = RID_FIRST_ADDR_SPACE + as; + if (rid > RID_LAST_ADDR_SPACE) + { + warning_at (loc, OPT_Wpragmas, "too many custom address spaces"); + return NULL; + } + + register_addr_space_identifier (id, rid); + return g_addr_space_mgr->create_custom_addr_space (id, as, loc); } /* Return identifier to look up for omp declare reduction. */ diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 80dd61d599e..88ad30c543a 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -71,6 +71,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "memmodel.h" #include "c-family/known-headers.h" +#include "addr-space.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -326,7 +327,7 @@ c_lex_one_token (c_parser *parser, c_token *token, bool raw = false) { addr_space_t as; as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE); - targetm.addr_space.diagnose_usage (as, token->location); + addr_space_diagnose_usage (as, token->location); token->id_kind = C_ID_ADDRSPACE; token->keyword = rid_code; break; diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 782414f8c8c..afaa3a63029 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "asan.h" +#include "addr-space.h" /* Possible cases of implicit conversions. Used to select diagnostic messages and control folding initializers in convert_for_assignment. */ @@ -308,12 +309,12 @@ addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common) *common = as1; return true; } - else if (targetm.addr_space.subset_p (as1, as2)) + else if (addr_space_subset_p (as1, as2)) { *common = as2; return true; } - else if (targetm.addr_space.subset_p (as2, as1)) + else if (addr_space_subset_p (as2, as1)) { *common = as1; return true; @@ -6015,18 +6016,18 @@ build_c_cast (location_t loc, tree type, tree expr) if (!addr_space_superset (as_to, as_from, &as_common)) { if (ADDR_SPACE_GENERIC_P (as_from)) - warning_at (loc, 0, "cast to %s address space pointer " + warning_at (loc, 0, "cast to %qs address space pointer " "from disjoint generic address space pointer", c_addr_space_name (as_to)); else if (ADDR_SPACE_GENERIC_P (as_to)) warning_at (loc, 0, "cast to generic address space pointer " - "from disjoint %s address space pointer", + "from disjoint %qs address space pointer", c_addr_space_name (as_from)); else - warning_at (loc, 0, "cast to %s address space pointer " - "from disjoint %s address space pointer", + warning_at (loc, 0, "cast to %qs address space pointer " + "from disjoint %qs address space pointer", c_addr_space_name (as_to), c_addr_space_name (as_from)); } @@ -7233,8 +7234,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, asl = TYPE_ADDR_SPACE (ttl); asr = TYPE_ADDR_SPACE (ttr); if (!null_pointer_constant_p (rhs) - && asr != asl && !targetm.addr_space.subset_p (asr, asl)) + && asr != asl && !addr_space_subset_p (asr, asl)) { + auto_diagnostic_group d; + bool diagnosed = true; switch (errtype) { case ic_argpass: @@ -7242,7 +7245,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, const char msg[] = G_("passing argument %d of %qE from " "pointer to non-enclosed address space"); if (warnopt) - warning_at (expr_loc, warnopt, msg, parmnum, rname); + diagnosed + = warning_at (expr_loc, warnopt, msg, parmnum, rname); else error_at (expr_loc, msg, parmnum, rname); break; @@ -7252,7 +7256,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, const char msg[] = G_("assignment from pointer to " "non-enclosed address space"); if (warnopt) - warning_at (location, warnopt, msg); + diagnosed = warning_at (location, warnopt, msg); else error_at (location, msg); break; @@ -7263,7 +7267,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, const char msg[] = G_("initialization from pointer to " "non-enclosed address space"); if (warnopt) - warning_at (location, warnopt, msg); + diagnosed = warning_at (location, warnopt, msg); else error_at (location, msg); break; @@ -7273,7 +7277,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, const char msg[] = G_("return from pointer to " "non-enclosed address space"); if (warnopt) - warning_at (location, warnopt, msg); + diagnosed = warning_at (location, warnopt, msg); else error_at (location, msg); break; @@ -7281,6 +7285,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, default: gcc_unreachable (); } + if (diagnosed) + { + if (errtype == ic_argpass) + inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); + else + inform (location, "expected %qT but pointer is of type %qT", + type, rhstype); + } return error_mark_node; } diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 55ff75bd78e..9dd958a5371 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -74,6 +74,7 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "builtins.h" #include "opts.h" +#include "addr-space.h" /* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to @@ -4248,12 +4249,12 @@ convert_debug_memory_address (scalar_int_mode mode, rtx x, { #ifndef POINTERS_EXTEND_UNSIGNED gcc_assert (mode == Pmode - || mode == targetm.addr_space.address_mode (as)); + || mode == addr_space_address_mode (as)); gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode); #else rtx temp; - gcc_assert (targetm.addr_space.valid_pointer_mode (mode, as)); + gcc_assert (addr_space_valid_pointer_mode (mode, as)); if (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode) return x; @@ -4694,7 +4695,7 @@ expand_debug_expr (tree exp) as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); - op0 = convert_debug_memory_address (targetm.addr_space.address_mode (as), + op0 = convert_debug_memory_address (addr_space_address_mode (as), op0, as); if (op0 == NULL_RTX) return NULL; @@ -4719,7 +4720,7 @@ expand_debug_expr (tree exp) return NULL; as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); - op0 = convert_debug_memory_address (targetm.addr_space.address_mode (as), + op0 = convert_debug_memory_address (addr_space_address_mode (as), op0, as); if (op0 == NULL_RTX) return NULL; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index e94efdf39fb..181edd9ef40 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -96,6 +96,7 @@ along with GCC; see the file COPYING3. If not see #include "i386-expand.h" #include "i386-features.h" #include "function-abi.h" +#include "addr-space.h" /* This file should be included last. */ #include "target-def.h" @@ -13718,6 +13719,8 @@ ix86_print_operand_address_as (FILE *file, rtx addr, bool vsib = false; int code = 0; + as = ensure_builtin_addr_space (as); + if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_VSIBADDR) { ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); diff --git a/gcc/coretypes.h b/gcc/coretypes.h index b4f530d57ac..f08932a1af7 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -166,11 +166,14 @@ class bitmap_view; /* Address space number for named address space support. */ typedef unsigned char addr_space_t; +#define ADDR_SPACE_T_MAX 255 /* The value of addr_space_t that represents the generic address space. */ #define ADDR_SPACE_GENERIC 0 #define ADDR_SPACE_GENERIC_P(AS) ((AS) == ADDR_SPACE_GENERIC) +struct custom_addr_space; + /* The major intermediate representations of GCC. */ enum ir_type { IR_GIMPLE, diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 32ddf835a91..1c741028a5e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -5961,6 +5961,14 @@ c_register_addr_space (const char * /*word*/, addr_space_t /*as*/) { } +/* Stub for c-common. Please keep in sync with c-decl.c. */ + +custom_addr_space * +c_register_custom_addr_space (tree, location_t) +{ + return NULL; +} + /* Return the number of operands in T that we care about for things like mangling. */ diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 6e6c580e329..bc298da8956 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -1412,6 +1412,10 @@ Address space identifiers may be used exactly like any other C type qualifier (e.g., @code{const} or @code{volatile}). See the N1275 document for more details. +As a further extension, GNU C supports user-defined address spaces +via @code{#pragma GCC custom_address_space}; see that pragma for +more details. + @anchor{AVR Named Address Spaces} @subsection AVR Named Address Spaces @@ -23331,6 +23335,7 @@ information. * Push/Pop Macro Pragmas:: * Function Specific Option Pragmas:: * Loop-Specific Pragmas:: +* Custom Address Space Pragmas:: @end menu @node AArch64 Pragmas @@ -24008,6 +24013,47 @@ The values of @math{0} and @math{1} block any unrolling of the loop. @end table +@node Custom Address Space Pragmas +@subsection Custom Address Space Pragmas + +@table @code +@item #pragma GCC custom_address_space (@var{name}) +@cindex pragma GCC custom_address_space + +As an extension, GNU C supports named address spaces on some targets as +defined in the N1275 draft of ISO/IEC DTR 18037. Support for named +address spaces in GCC will evolve as the draft technical report +changes. + +This pragma creates a user-defined address space with the given name +within the translation unit, supplementing the implicit target-specific +address spaces, and the ``generic'' address space. + +All custom address spaces are disjoint from each other and from all +built-in address spaces (including the generic address space). +For example, given: + +@smallexample +#pragma GCC custom_address_space(__kernel) +#pragma GCC custom_address_space(__user) +void __kernel *kernel_ptr; +void __user *user_ptr; +@end smallexample + +then GNU C will issue a diagnostic on attempts to use a convert between +@code{void __kernel *} and a @code {void __user *}, or between these +pointers and a plain @code{void *}. + +Although new address spaces created this way are disjoint and thus are +not equivalent in terms of type-checking, they are all equivalent to the +generic address space in terms of code generation. + +The number of user-defined address spaces allowed in a translation unit +is target-dependent, but very limited - the total number of target-specific +and user-defined address spaces in a translation unit must not exceed 15. + +@end table + @node Unnamed Fields @section Unnamed Structure and Union Fields @cindex @code{struct} diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index fb0e3381e5b..028d4235054 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -97,6 +97,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "file-prefix-map.h" /* remap_debug_filename() */ +#include "addr-space.h" static void dwarf2out_source_line (unsigned int, unsigned int, const char *, int, bool); @@ -13771,7 +13772,7 @@ modified_type_die (tree type, int cv_quals, bool reverse, addr_space_t as = TYPE_ADDR_SPACE (item_type); if (!ADDR_SPACE_GENERIC_P (as)) { - int action = targetm.addr_space.debug (as); + int action = addr_space_debug (as); if (action >= 0) { /* Positive values indicate an address_class. */ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index e6158f243c0..6419235c8d5 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -63,6 +63,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "gimple-ssa.h" #include "gimplify.h" +#include "addr-space.h" struct target_rtl default_target_rtl; #if SWITCHABLE_TARGET @@ -2349,7 +2350,7 @@ adjust_address_1 (rtx memref, machine_mode mode, poly_int64 offset, unsigned HOST_WIDE_INT max_align; #ifdef POINTERS_EXTEND_UNSIGNED scalar_int_mode pointer_mode - = targetm.addr_space.pointer_mode (attrs.addrspace); + = addr_space_pointer_mode (attrs.addrspace); #endif /* VOIDmode means no mode change for change_address_1. */ diff --git a/gcc/explow.c b/gcc/explow.c index a35423f5d16..81c688bb1c3 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "common/common-target.h" #include "output.h" +#include "addr-space.h" static rtx break_out_memory_refs (rtx); @@ -310,8 +311,8 @@ convert_memory_address_addr_space_1 (scalar_int_mode to_mode ATTRIBUTE_UNUSED, if (GET_MODE (x) == to_mode) return x; - pointer_mode = targetm.addr_space.pointer_mode (as); - address_mode = targetm.addr_space.address_mode (as); + pointer_mode = addr_space_pointer_mode (as); + address_mode = addr_space_address_mode (as); from_mode = to_mode == pointer_mode ? address_mode : pointer_mode; /* Here we handle some special cases. If none of them apply, fall through @@ -433,7 +434,7 @@ rtx memory_address_addr_space (machine_mode mode, rtx x, addr_space_t as) { rtx oldx = x; - scalar_int_mode address_mode = targetm.addr_space.address_mode (as); + scalar_int_mode address_mode = addr_space_address_mode (as); x = convert_memory_address_addr_space (address_mode, x, as); @@ -469,7 +470,7 @@ memory_address_addr_space (machine_mode mode, rtx x, addr_space_t as) transformations can make better code. */ { rtx orig_x = x; - x = targetm.addr_space.legitimize_address (x, oldx, mode, as); + x = addr_space_legitimize_address (x, oldx, mode, as); if (orig_x != x && memory_address_addr_space_p (mode, x, as)) goto done; } @@ -853,7 +854,7 @@ promote_mode (const_tree type ATTRIBUTE_UNUSED, machine_mode mode, case REFERENCE_TYPE: case POINTER_TYPE: *punsignedp = POINTERS_EXTEND_UNSIGNED; - return targetm.addr_space.address_mode + return addr_space_address_mode (TYPE_ADDR_SPACE (TREE_TYPE (type))); #endif diff --git a/gcc/expr.c b/gcc/expr.c index 5673902b1fc..bfecf416aa6 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "rtx-vector-builder.h" #include "tree-pretty-print.h" #include "flags.h" +#include "addr-space.h" /* If this is nonzero, we do not bother generating VOLATILE @@ -6191,7 +6192,7 @@ store_expr (tree exp, rtx target, int call_param_p, else { machine_mode pointer_mode - = targetm.addr_space.pointer_mode (MEM_ADDR_SPACE (target)); + = addr_space_pointer_mode (MEM_ADDR_SPACE (target)); machine_mode address_mode = get_address_mode (target); /* Compute the size of the data to copy from the string. */ @@ -8537,8 +8538,8 @@ expand_expr_addr_expr (tree exp, rtx target, machine_mode tmode, if (POINTER_TYPE_P (TREE_TYPE (exp))) { as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp))); - address_mode = targetm.addr_space.address_mode (as); - pointer_mode = targetm.addr_space.pointer_mode (as); + address_mode = addr_space_address_mode (as); + pointer_mode = addr_space_pointer_mode (as); } /* We can get called with some Weird Things if the user does silliness @@ -9125,10 +9126,10 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, /* Ask target code to handle conversion between pointers to overlapping address spaces. */ - if (targetm.addr_space.subset_p (as_to, as_from) - || targetm.addr_space.subset_p (as_from, as_to)) + if (addr_space_subset_p (as_to, as_from) + || addr_space_subset_p (as_from, as_to)) { - op0 = targetm.addr_space.convert (op0, treeop0_type, type); + op0 = addr_space_convert (op0, treeop0_type, type); } else { @@ -10727,7 +10728,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, /* Writing into CONST_DECL is always invalid, but handle it gracefully. */ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp)); - scalar_int_mode address_mode = targetm.addr_space.address_mode (as); + scalar_int_mode address_mode = addr_space_address_mode (as); op0 = expand_expr_addr_expr_1 (exp, NULL_RTX, address_mode, EXPAND_NORMAL, as); op0 = memory_address_addr_space (mode, op0, as); @@ -10901,7 +10902,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, REF_REVERSE_STORAGE_ORDER (exp) = reverse; return expand_expr (exp, target, tmode, modifier); } - address_mode = targetm.addr_space.address_mode (as); + address_mode = addr_space_address_mode (as); if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR))) { tree mask = gimple_assign_rhs2 (def_stmt); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 90d82257ae7..dc5d8729508 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see #include "vec-perm-indices.h" #include "asan.h" #include "gimple-range.h" +#include "addr-space.h" /* Nonzero if we are folding constants inside an initializer; zero otherwise. */ @@ -1744,7 +1745,7 @@ const_unop (enum tree_code code, tree type, tree arg0) /* If the source address is 0, and the source address space cannot have a valid object at 0, fold to dest type null. */ if (integer_zerop (arg0) - && !(targetm.addr_space.zero_address_valid + && !(addr_space_zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (arg0)))))) return fold_convert_const (code, type, arg0); break; diff --git a/gcc/gimple.c b/gcc/gimple.c index 1e0fad92e15..1cf4bc8ffda 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-modref-tree.h" #include "ipa-modref.h" #include "dbgcnt.h" +#include "addr-space.h" /* All the tuples have their operand vector (if present) at the very bottom of the structure. Therefore, the offset required to find the @@ -3023,7 +3024,7 @@ check_loadstore (gimple *, tree op, tree, void *data) { /* Some address spaces may legitimately dereference zero. */ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op)); - if (targetm.addr_space.zero_address_valid (as)) + if (addr_space_zero_address_valid (as)) return false; return operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0); diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 0195b4fb9c3..53066fcb675 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -132,6 +132,7 @@ #include "print-rtl.h" #include "function-abi.h" #include "rtl-iter.h" +#include "addr-space.h" /* Value of LRA_CURR_RELOAD_NUM at the beginning of BB of the current insn. Remember that LRA_CURR_RELOAD_NUM is the number of emitted @@ -335,7 +336,7 @@ valid_address_p (machine_mode mode ATTRIBUTE_UNUSED, win: return 1; #else - return targetm.addr_space.legitimate_address_p (mode, addr, 0, as); + return addr_space_legitimate_address_p (mode, addr, 0, as); #endif } diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc index a0e4543d8a3..fec58093cd0 100644 --- a/gcc/pointer-query.cc +++ b/gcc/pointer-query.cc @@ -41,7 +41,7 @@ #include "pointer-query.h" #include "tree-pretty-print.h" #include "tree-ssanames.h" -#include "target.h" +#include "addr-space.h" static bool compute_objsize_r (tree, gimple *, int, access_ref *, ssa_name_limit_t &, pointer_query *); @@ -1889,7 +1889,7 @@ compute_objsize_r (tree ptr, gimple *stmt, int ostype, access_ref *pref, { tree deref_type = TREE_TYPE (TREE_TYPE (ptr)); addr_space_t as = TYPE_ADDR_SPACE (deref_type); - if (targetm.addr_space.zero_address_valid (as)) + if (addr_space_zero_address_valid (as)) pref->set_max_size_range (); else pref->sizrng[0] = pref->sizrng[1] = 0; diff --git a/gcc/recog.c b/gcc/recog.c index 5a42c45361d..7deb9c7285e 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "reload.h" #include "tree-pass.h" #include "function-abi.h" +#include "addr-space.h" #ifndef STACK_POP_CODE #if STACK_GROWS_DOWNWARD @@ -1791,7 +1792,7 @@ memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED, win: return true; #else - return targetm.addr_space.legitimate_address_p (mode, addr, 0, as); + return addr_space_legitimate_address_p (mode, addr, 0, as); #endif } @@ -2423,9 +2424,9 @@ offsettable_address_addr_space_p (int strictp, machine_mode mode, rtx y, machine_mode address_mode = GET_MODE (y); if (address_mode == VOIDmode) - address_mode = targetm.addr_space.address_mode (as); + address_mode = addr_space_address_mode (as); #ifdef POINTERS_EXTEND_UNSIGNED - machine_mode pointer_mode = targetm.addr_space.pointer_mode (as); + machine_mode pointer_mode = addr_space_pointer_mode (as); #endif /* ??? How much offset does an offsettable BLKmode reference need? diff --git a/gcc/reload.c b/gcc/reload.c index 4c55ca58a5f..b1018ca684a 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -106,6 +106,7 @@ a register with any other reload. */ #include "reload.h" #include "addresses.h" #include "function-abi.h" +#include "addr-space.h" /* True if X is a constant that can be forced into the constant pool. MODE is the mode of the operand, or VOIDmode if not known. */ @@ -2172,7 +2173,7 @@ strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED, win: return true; #else - return targetm.addr_space.legitimate_address_p (mode, addr, 1, as); + return addr_space_legitimate_address_p (mode, addr, 1, as); #endif } @@ -5242,7 +5243,7 @@ find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad, { machine_mode address_mode = GET_MODE (ad); if (address_mode == VOIDmode) - address_mode = targetm.addr_space.address_mode (as); + address_mode = addr_space_address_mode (as); /* If AD is an address in the constant pool, the MEM rtx may be shared. Unshare it so we can safely alter it. */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index d37f7789b20..1046b359c30 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl-iter.h" #include "hard-reg-set.h" #include "function-abi.h" +#include "addr-space.h" /* Forward declarations */ static void set_of_1 (rtx, const_rtx, void *); @@ -6278,7 +6279,7 @@ get_address_mode (rtx mem) mode = GET_MODE (XEXP (mem, 0)); if (mode != VOIDmode) return as_a (mode); - return targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem)); + return addr_space_address_mode (MEM_ADDR_SPACE (mem)); } /* Split up a CONST_DOUBLE or integer constant rtx diff --git a/gcc/testsuite/gcc.dg/custom-address-space-1.c b/gcc/testsuite/gcc.dg/custom-address-space-1.c new file mode 100644 index 00000000000..9ca1157a730 --- /dev/null +++ b/gcc/testsuite/gcc.dg/custom-address-space-1.c @@ -0,0 +1,174 @@ +/* Verify that we can create multiple custom address spaces, + that they are treated as disjoint from each other and from + the generic address space. */ + +/* Avoid using "-ansi". */ +/* { dg-options "" } */ + +#define __kernel +#pragma GCC custom_address_space(__user) +#pragma GCC custom_address_space(__iomem) +#pragma GCC custom_address_space(__percpu) +#pragma GCC custom_address_space(__rcu) + +void *p; +void __kernel *p_kernel; +void __user *p_user; +void __iomem *p_iomem; +void __percpu *p_percpu; +void __rcu *p_rcu; + +extern void accepts_p (void *); /* { dg-message "24: expected 'void \\*' but argument is of type '__user void \\*'" } */ +extern void accepts_p_kernel (void __kernel *); +extern void accepts_p_user (void __user *); + +void test_argpass_to_p (void) +{ + accepts_p (p); + accepts_p (p_kernel); + accepts_p (p_user); /* { dg-error "passing argument 1 of 'accepts_p' from pointer to non-enclosed address space" } */ +} + +void test_init_p (void) +{ + void *local_p_1 = p; + void *local_p_2 = p_kernel; + void *local_p_3 = p_user; /* { dg-error "initialization from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ + void *local_p_4 = p_iomem; /* { dg-error "initialization from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__iomem void \\*'" "" { target *-*-* } .-1 } */ +} + +void test_init_p_kernel (void) +{ + void __kernel *local_p_1 = p; + void __kernel *local_p_2 = p_kernel; + void __kernel *local_p_3 = p_user; /* { dg-error "initialization from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ +} + +void test_init_p_user (void) +{ + void __user *local_p_1 = p; /* { dg-error "initialization from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + void __user *local_p_2 = p_kernel; /* { dg-error "initialization from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + void __user *local_p_3 = p_user; +} + +void test_assign_to_p (void) +{ + p = p; + p = p_kernel; + p = p_user; /* { dg-error "assignment from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ + // etc +} + +void test_assign_to_p_kernel (void) +{ + p_kernel = p; + p_kernel = p_kernel; + p_kernel = p_user; /* { dg-error "assignment from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ + // etc +} + +void test_assign_to_p_user (void) +{ + p_user = p; /* { dg-error "assignment from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + p_user = p_kernel; /* { dg-error "assignment from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + p_user = p_user; + // etc +} + +void *test_return_p (int i) +{ + switch (i) + { + default: + case 0: + return p; + case 1: + return p_kernel; + case 2: + return p_user; /* { dg-error "return from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ + } +} + +void __kernel *test_return_p_kernel (int i) +{ + switch (i) + { + default: + case 0: + return p; + case 1: + return p_kernel; + case 2: + return p_user; /* { dg-error "return from pointer to non-enclosed address space" } */ + /* { dg-message "expected 'void \\*' but pointer is of type '__user void \\*'" "" { target *-*-* } .-1 } */ + } +} + +void __user *test_return_p_user (int i) +{ + switch (i) + { + default: + case 0: + return p; /* { dg-error "return from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + case 1: + return p_kernel; /* { dg-error "return from pointer to non-enclosed address space" } */ + /* { dg-message "expected '__user void \\*' but pointer is of type 'void \\*'" "" { target *-*-* } .-1 } */ + case 2: + return p_user; + } +} + +void test_cast_k_to_u (void) +{ + p_user = (void __user *)p_kernel; /* { dg-warning "cast to '__user' address space pointer from disjoint generic address space pointer" } */ +} + +void test_cast_u_to_k (void) +{ + p_kernel = (void __kernel *)p_user; /* { dg-warning "cast to generic address space pointer from disjoint '__user' address space pointer" } */ +} + +void test_cast_user_to_iomem (void) +{ + p_iomem = (void __iomem *)p_user; /* { dg-warning "cast to '__iomem' address space pointer from disjoint '__user' address space pointer" } */ +} + +int test_deref_read (int __user *p) +{ + return *p; // FIXME: should we have a way to disallow direct access? +} + +void test_deref_write (int __user *p, int i) +{ + *p = i; // FIXME: should we have a way to disallow direct access? +} + +typedef struct foo { int i; } __user *foo_ptr_t; + +void __user * +test_pass_through (void __user *ptr) +{ + return ptr; +} + +#define NULL ((void *)0) + +void __user * +test_return_null_p_user () +{ + return NULL; +} + +// etc diff --git a/gcc/testsuite/gcc.dg/custom-address-space-2.c b/gcc/testsuite/gcc.dg/custom-address-space-2.c new file mode 100644 index 00000000000..7a07f3b134a --- /dev/null +++ b/gcc/testsuite/gcc.dg/custom-address-space-2.c @@ -0,0 +1,21 @@ +/* Verify that we fail gracefully if the user defines too many address spaces. */ +/* Avoid using "-ansi". */ +/* { dg-options "" } */ + +#pragma GCC custom_address_space(__cas_01) +#pragma GCC custom_address_space(__cas_02) +#pragma GCC custom_address_space(__cas_03) +#pragma GCC custom_address_space(__cas_04) +#pragma GCC custom_address_space(__cas_05) +#pragma GCC custom_address_space(__cas_06) +#pragma GCC custom_address_space(__cas_07) +#pragma GCC custom_address_space(__cas_08) +#pragma GCC custom_address_space(__cas_09) +#pragma GCC custom_address_space(__cas_10) +#pragma GCC custom_address_space(__cas_11) +#pragma GCC custom_address_space(__cas_12) +#pragma GCC custom_address_space(__cas_13) +#pragma GCC custom_address_space(__cas_14) /* { dg-warning "too many custom address spaces" } */ +#pragma GCC custom_address_space(__cas_15) /* { dg-warning "too many custom address spaces" } */ + +// FIXME: how to filter this by target; it's going to vary by target diff --git a/gcc/testsuite/gcc.dg/custom-address-space-3.c b/gcc/testsuite/gcc.dg/custom-address-space-3.c new file mode 100644 index 00000000000..426d6ce5c64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/custom-address-space-3.c @@ -0,0 +1,15 @@ +/* Verify that we can successfully compile code with a custom address space. */ +/* Avoid using "-ansi". */ +/* { dg-options "" } */ + +#pragma GCC custom_address_space(__user) + +int test_1 (int __user *p) +{ + return *p; +} + +void test_2 (int __user *p, int val) +{ + *p = val; +} diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index f35556db2f7..e75ab19c8f0 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-affine.h" #include "gimplify.h" #include "builtins.h" +#include "addr-space.h" /* FIXME: We compute address costs using RTL. */ #include "tree-ssa-address.h" @@ -192,8 +193,8 @@ rtx addr_for_mem_ref (struct mem_address *addr, addr_space_t as, bool really_expand) { - scalar_int_mode address_mode = targetm.addr_space.address_mode (as); - scalar_int_mode pointer_mode = targetm.addr_space.pointer_mode (as); + scalar_int_mode address_mode = addr_space_address_mode (as); + scalar_int_mode pointer_mode = addr_space_pointer_mode (as); rtx address, sym, bse, idx, st, off; struct mem_addr_template *templ; @@ -576,7 +577,7 @@ multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, machine_mode mode, valid_mult = valid_mult_list[data_index]; if (!valid_mult) { - machine_mode address_mode = targetm.addr_space.address_mode (as); + machine_mode address_mode = addr_space_address_mode (as); rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1); rtx reg2 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2); rtx addr, scaled; @@ -622,7 +623,7 @@ most_expensive_mult_to_index (tree type, struct mem_address *parts, aff_tree *addr, bool speed) { addr_space_t as = TYPE_ADDR_SPACE (type); - machine_mode address_mode = targetm.addr_space.address_mode (as); + machine_mode address_mode = addr_space_address_mode (as); HOST_WIDE_INT coef; unsigned best_mult_cost = 0, acost; tree mult_elt = NULL_TREE, elt; diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 4a498abe3b0..0cda74825e8 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -131,6 +131,7 @@ along with GCC; see the file COPYING3. If not see #include "builtins.h" #include "tree-vectorizer.h" #include "dbgcnt.h" +#include "addr-space.h" /* For lang_hooks.types.type_for_mode. */ #include "langhooks.h" @@ -2606,7 +2607,7 @@ addr_offset_valid_p (struct iv_use *use, poly_int64 offset) addr = (*addr_list)[list_index]; if (!addr) { - addr_mode = targetm.addr_space.address_mode (as); + addr_mode = addr_space_address_mode (as); reg = gen_raw_REG (addr_mode, LAST_VIRTUAL_REGISTER + 1); addr = gen_rtx_fmt_ee (PLUS, addr_mode, reg, NULL_RTX); (*addr_list)[list_index] = addr; @@ -3729,7 +3730,7 @@ static rtx produce_memory_decl_rtl (tree obj, int *regno) { addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (obj)); - machine_mode address_mode = targetm.addr_space.address_mode (as); + machine_mode address_mode = addr_space_address_mode (as); rtx x; gcc_assert (obj); diff --git a/gcc/tree.c b/gcc/tree.c index 845228a055b..119cef9cfcc 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-fold.h" #include "escaped_string.h" #include "gimple-range.h" +#include "addr-space.h" /* Tree code classes. */ @@ -6829,7 +6830,7 @@ build_pointer_type_for_mode (tree to_type, machine_mode mode, if (mode == VOIDmode) { addr_space_t as = TYPE_ADDR_SPACE (to_type); - mode = targetm.addr_space.pointer_mode (as); + mode = addr_space_pointer_mode (as); } /* If the pointed-to type has the may_alias attribute set, force @@ -6901,7 +6902,7 @@ build_reference_type_for_mode (tree to_type, machine_mode mode, if (mode == VOIDmode) { addr_space_t as = TYPE_ADDR_SPACE (to_type); - mode = targetm.addr_space.pointer_mode (as); + mode = addr_space_pointer_mode (as); } /* If the pointed-to type has the may_alias attribute set, force diff --git a/gcc/varasm.c b/gcc/varasm.c index 09316c62050..d328adc0a7b 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -61,6 +61,7 @@ along with GCC; see the file COPYING3. If not see #include "alloc-pool.h" #include "toplev.h" #include "opts.h" +#include "addr-space.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -1620,7 +1621,7 @@ make_decl_rtl (tree decl) if (TREE_TYPE (decl) != error_mark_node) { addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl)); - address_mode = targetm.addr_space.address_mode (as); + address_mode = addr_space_address_mode (as); } x = gen_rtx_SYMBOL_REF (address_mode, name); } @@ -5178,7 +5179,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, resolving it. */ if (TREE_CODE (exp) == NOP_EXPR && POINTER_TYPE_P (TREE_TYPE (exp)) - && targetm.addr_space.valid_pointer_mode + && addr_space_valid_pointer_mode (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)), TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp))))) { @@ -5188,7 +5189,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, pointer modes. */ while (TREE_CODE (exp) == NOP_EXPR && POINTER_TYPE_P (TREE_TYPE (exp)) - && targetm.addr_space.valid_pointer_mode + && addr_space_valid_pointer_mode (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)), TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp))))) exp = TREE_OPERAND (exp, 0);