@@ -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 \
new file mode 100644
@@ -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
+<http://www.gnu.org/licenses/>. */
+
+#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> ()) 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;
new file mode 100644
@@ -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
+<http://www.gnu.org/licenses/>. */
+
+#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<custom_addr_space *, va_gc> *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 */
@@ -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");
@@ -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);
@@ -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 <scalar_int_mode> (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;
@@ -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;
@@ -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> ()) addr_space_manager ();
#ifdef REGISTER_TARGET_PRAGMAS
REGISTER_TARGET_PRAGMAS ();
#endif
@@ -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. */
@@ -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;
@@ -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;
}
@@ -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;
@@ -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);
@@ -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,
@@ -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. */
@@ -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}
@@ -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. */
@@ -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. */
@@ -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
@@ -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);
@@ -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;
@@ -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);
@@ -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
}
@@ -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;
@@ -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?
@@ -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. */
@@ -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 <scalar_int_mode> (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
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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;
+}
@@ -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;
@@ -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);
@@ -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
@@ -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);