This adds two hooks to determine address spaces for local and global
variables, and changes various places in the compiler to ensure stuff
goes to the right place.
If a type is given an address space in this way, the
TYPE_QUAL_AS_IMPLICIT is set. Such a flag is needed to properly handle
such types in situations like passing them to varargs and old-style
functions, and to make typeof behave as expected.
gcc/c-family/
* c-common.c (c_common_nodes_and_builtins): If globals need to go into
a specific address space, rebuild the char array type nodes
accordingly.
gcc/c/
* c-decl.c (start_function): Make the result live in the for_frame
address space.
(build_compound_literal): Choose an appropriate address
space.
(grokdeclarator): If no address space is specified, use the frame or
global address space implicitly.
* c-parser.c (c_parser_typeof_specifier): If it is set, drop the
address space from the returned type.
* c-typeck.c (convert_arguments): If we have no type, and a pointer arg
which points to a type with implicit address space, convert the pointer
so as to point to the generic address space.
gcc/
* target.def (for_frame, for_global): New hooks in addr_space.
* cfgexpand.c (expand_one_stack_var_at): Use the frame address space.
* emit-rtl.c (gen_frame_mem): Likewise.
* function.c (assign_stack_local_1, assign_stack_temp_for_type):
Likewise.
(assign_parms_augmented_arg_list, assign_parms_find_data_types):
Use build_pointer_type_in_frame.
* calls.c (initialize_argument_information): When we make a copy,
ensure the decl for it has the for_frame address space.
* targhooks.c (std_gimplify_va_arg_expr): If an arg is passed by
reference, assume it lives in the for_frame address space if that
isn't the generic one.
* tree-core.h (struct tree_base): Take a new as_implicit_flag out of
spare0.
(enum cv_qualifier): Add TYPE_QUAL_AS_IMPLICIT.
* tree.h (build_pointer_type_in_frame): Declare.
(TYPE_AS_IMPLICIT): New macro.
(TYPE_QUALS): Take TYPE_QUAL_AS_IMPLICIT into account.
* tree.c (set_type_quals): Likewise.
(build_pointer_type_in_frame): New function.
* targhooks.c (hook_return_generic_addr_space): New function.
(hook_return_generic_addr_space_bool): New function.
* targhooks.h (hook_return_generic_addr_space,
(hook_return_generic_addr_space_bool): Declare.
* tree-switch-conversion.c: Include "target.h".
(build_one_array): Use the for_global hook to determine address space.
* varasm.c (build_constant_desc): Likewise.
* doc/tm.texi.in (TARGET_ADDR_SPACE_FOR_FRAME,
TARGET_ADDR_SPACE_FOR_GLOBAL): Add hooks.
* doc/tm.texi: Regenerate.
------------------------------------------------------------------------
===================================================================
@@ -10330,6 +10330,17 @@ guaranteed that one of the two address s
as determined by the @code{TARGET_ADDR_SPACE_SUBSET_P} target hook.
@end deftypefn
+@deftypefn {Target Hook} addr_space_t TARGET_ADDR_SPACE_FOR_FRAME (void)
+Define this if memory locations in the stack frame should use a different
+address space than the default. It returns the address space to use.
+@end deftypefn
+
+@deftypefn {Target Hook} addr_space_t TARGET_ADDR_SPACE_FOR_GLOBAL (bool @var{constp})
+Define this if global memory locations should use a different
+address space than the default. It returns the address space to use.
+If @var{constp} is nonzero, the variable will be constant.
+@end deftypefn
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
===================================================================
@@ -7669,6 +7669,10 @@ c_register_addr_space ("__ea", ADDR_SPAC
@hook TARGET_ADDR_SPACE_CONVERT
+@hook TARGET_ADDR_SPACE_FOR_FRAME
+
+@hook TARGET_ADDR_SPACE_FOR_GLOBAL
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
===================================================================
@@ -1642,7 +1642,17 @@ std_gimplify_va_arg_expr (tree valist, t
indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
if (indirect)
- type = build_pointer_type (type);
+ {
+ /* We assume that if there is a frame address space, the caller makes
+ a copy. */
+ addr_space_t as = targetm.addr_space.for_frame ();
+ if (!ADDR_SPACE_GENERIC_P (as))
+ type
+ = build_qualified_type (type,
+ TYPE_QUALS_NO_ADDR_SPACE (type)
+ | ENCODE_QUAL_ADDR_SPACE (as));
+ type = build_pointer_type (type);
+ }
align = PARM_BOUNDARY / BITS_PER_UNIT;
boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type);
@@ -1750,4 +1760,16 @@ can_use_doloop_if_innermost (double_int,
return loop_depth == 1;
}
+addr_space_t
+hook_return_generic_addr_space (void)
+{
+ return ADDR_SPACE_GENERIC;
+}
+
+addr_space_t
+hook_return_generic_addr_space_bool (bool)
+{
+ return ADDR_SPACE_GENERIC;
+}
+
#include "gt-targhooks.h"
===================================================================
@@ -164,6 +164,9 @@ extern rtx default_addr_space_legitimize
addr_space_t);
extern bool default_addr_space_subset_p (addr_space_t, addr_space_t);
extern rtx default_addr_space_convert (rtx, tree, tree);
+extern addr_space_t hook_return_generic_addr_space (void);
+extern addr_space_t hook_return_generic_addr_space_bool (bool);
+
extern unsigned int default_case_values_threshold (void);
extern bool default_have_conditional_execution (void);
===================================================================
@@ -5560,6 +5560,23 @@ c_common_nodes_and_builtins (void)
char32_array_type_node
= build_array_type (char32_type_node, array_domain_type);
+ addr_space_t as = targetm.addr_space.for_global (true);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ int quals = ENCODE_QUAL_ADDR_SPACE (as) | TYPE_QUAL_AS_IMPLICIT;
+ char_array_type_node
+ = build_array_type (build_qualified_type (char_type_node, quals),
+ array_domain_type);
+ char16_array_type_node
+ = build_array_type (build_qualified_type (char16_type_node, quals),
+ array_domain_type);
+ char32_array_type_node
+ = build_array_type (build_qualified_type (char32_type_node, quals),
+ array_domain_type);
+ wchar_array_type_node
+ = build_array_type (build_qualified_type (wchar_type_node, quals),
+ array_domain_type);
+ }
wint_type_node =
TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
===================================================================
@@ -2994,6 +2994,9 @@ c_parser_typeof_specifier (c_parser *par
error_at (here, "%<typeof%> applied to a bit-field");
mark_exp_read (expr.value);
ret.spec = TREE_TYPE (expr.value);
+ if (ret.spec != error_mark_node && TYPE_AS_IMPLICIT (ret.spec))
+ ret.spec = build_qualified_type (ret.spec,
+ TYPE_QUALS_NO_ADDR_SPACE (ret.spec));
was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
/* This is returned with the type so that when the type is
evaluated, this can be evaluated. */
===================================================================
@@ -3312,8 +3312,19 @@ convert_arguments (tree typelist, vec<tr
return -1;
}
else
- /* Convert `short' and `char' to full-size `int'. */
- parmval = default_conversion (val);
+ {
+ if (POINTER_TYPE_P (valtype)
+ && TYPE_AS_IMPLICIT (TREE_TYPE (valtype)))
+ {
+ tree basetype = TREE_TYPE (valtype);
+ int quals = TYPE_QUALS_NO_ADDR_SPACE (basetype);
+ basetype = build_qualified_type (basetype, quals);
+ basetype = build_pointer_type (basetype);
+ val = convert (basetype, val);
+ }
+ /* Convert `short' and `char' to full-size `int'. */
+ parmval = default_conversion (val);
+ }
(*values)[parmnum] = parmval;
if (parmval == error_mark_node)
===================================================================
@@ -4665,6 +4665,17 @@ build_compound_literal (location_t loc,
|| init == error_mark_node)
return error_mark_node;
+ addr_space_t as;
+ if (current_function_decl)
+ as = targetm.addr_space.for_frame ();
+ else
+ as = targetm.addr_space.for_global (!non_const);
+ if (!ADDR_SPACE_GENERIC_P (as)
+ && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type)))
+ type = build_qualified_type (type,
+ (TYPE_QUALS_NO_ADDR_SPACE (type)
+ | ENCODE_QUAL_ADDR_SPACE (as)));
+
decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
@@ -5850,6 +5861,33 @@ grokdeclarator (const struct c_declarato
c_addr_space_name (address_space));
}
}
+ else if ((current_function_scope
+ || (decl_context == PARM
+ && TREE_CODE (type) != ARRAY_TYPE
+ && TREE_CODE (type) != VOID_TYPE))
+ && (storage_class == csc_auto || storage_class == csc_none)
+ && decl_context != TYPENAME)
+ {
+ addr_space_t new_as = targetm.addr_space.for_frame ();
+ if (!ADDR_SPACE_GENERIC_P (new_as))
+ type_quals = (CLEAR_QUAL_ADDR_SPACE (type_quals)
+ | TYPE_QUAL_AS_IMPLICIT
+ | ENCODE_QUAL_ADDR_SPACE (new_as));
+ }
+ else if ((!current_function_scope
+ || storage_class == csc_static
+ || storage_class == csc_extern)
+ && decl_context == NORMAL
+ && declarator->kind != cdk_function
+ && storage_class != csc_typedef)
+ {
+ bool is_const = (type_quals & TYPE_QUAL_CONST) != 0;
+ addr_space_t new_as = targetm.addr_space.for_global (is_const);
+ if (!ADDR_SPACE_GENERIC_P (new_as))
+ type_quals = (CLEAR_QUAL_ADDR_SPACE (type_quals)
+ | TYPE_QUAL_AS_IMPLICIT
+ | ENCODE_QUAL_ADDR_SPACE (new_as));
+ }
/* Check the type and width of a bit-field. */
if (bitfield)
@@ -8024,6 +8062,12 @@ start_function (struct c_declspecs *decl
declare_parm_level ();
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
+ addr_space_t as = targetm.addr_space.for_frame ();
+ if (!ADDR_SPACE_GENERIC_P (as))
+ restype
+ = build_qualified_type (restype,
+ TYPE_QUALS_NO_ADDR_SPACE (restype)
+ | ENCODE_QUAL_ADDR_SPACE (as));
resdecl = build_decl (loc, RESULT_DECL, NULL_TREE, restype);
DECL_ARTIFICIAL (resdecl) = 1;
DECL_IGNORED_P (resdecl) = 1;
===================================================================
@@ -3017,6 +3017,21 @@ as determined by the @code{TARGET_ADDR_S
rtx, (rtx op, tree from_type, tree to_type),
default_addr_space_convert)
+DEFHOOK
+(for_frame,
+ "Define this if memory locations in the stack frame should use a different\n\
+address space than the default. It returns the address space to use.",
+ addr_space_t, (void),
+ hook_return_generic_addr_space)
+
+DEFHOOK
+(for_global,
+ "Define this if global memory locations should use a different\n\
+address space than the default. It returns the address space to use.\n\
+If @var{constp} is nonzero, the variable will be constant.",
+ addr_space_t, (bool constp),
+ hook_return_generic_addr_space_bool)
+
HOOK_VECTOR_END (addr_space)
#undef HOOK_PREFIX
===================================================================
@@ -6078,6 +6078,7 @@ set_type_quals (tree type, int type_qual
TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
+ TYPE_AS_IMPLICIT (type) = (type_quals & TYPE_QUAL_AS_IMPLICIT) != 0;
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
@@ -7581,6 +7582,22 @@ build_pointer_type (tree to_type)
return build_pointer_type_for_mode (to_type, pointer_mode, false);
}
+/* Like build_pointer_type, but adjust the address space of the resulting
+ pointer type as appropriate for an object living in the stack frame. */
+
+tree
+build_pointer_type_in_frame (tree to_type)
+{
+ tree type = build_pointer_type (to_type);
+ addr_space_t as = targetm.addr_space.for_frame ();
+ if (!ADDR_SPACE_GENERIC_P (as))
+ type
+ = build_qualified_type (type,
+ TYPE_QUALS_NO_ADDR_SPACE (type)
+ | ENCODE_QUAL_ADDR_SPACE (as));
+ return type;
+}
+
/* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */
tree
===================================================================
@@ -1628,6 +1628,11 @@ extern void protected_set_expr_location
/* If nonzero, type's name shouldn't be emitted into debug info. */
#define TYPE_NAMELESS(NODE) (TYPE_CHECK (NODE)->base.u.bits.nameless_flag)
+/* If nonzero, the address space was chosen implicitly due to target
+ requirements. */
+#define TYPE_AS_IMPLICIT(NODE) \
+ (TYPE_CHECK (NODE)->base.u.bits.as_implicit_flag)
+
/* The address space the type is in. */
#define TYPE_ADDR_SPACE(NODE) (TYPE_CHECK (NODE)->base.u.bits.address_space)
@@ -1649,6 +1654,7 @@ extern void protected_set_expr_location
| (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
| (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
| (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \
+ | (TYPE_AS_IMPLICIT (NODE) * TYPE_QUAL_AS_IMPLICIT) \
| (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
/* The same as TYPE_QUALS without the address space qualifications. */
@@ -3604,6 +3610,7 @@ extern tree unsigned_type_for (tree);
extern tree truth_type_for (tree);
extern tree build_pointer_type_for_mode (tree, enum machine_mode, bool);
extern tree build_pointer_type (tree);
+extern tree build_pointer_type_in_frame (tree);
extern tree build_reference_type_for_mode (tree, enum machine_mode, bool);
extern tree build_reference_type (tree);
extern tree build_vector_type_for_mode (tree, enum machine_mode);
===================================================================
@@ -478,6 +478,7 @@ assign_stack_local_1 (enum machine_mode
x = gen_rtx_MEM (mode, addr);
set_mem_align (x, alignment_in_bits);
+ set_mem_addr_space (x, targetm.addr_space.for_frame ());
MEM_NOTRAP_P (x) = 1;
stack_slot_list
@@ -886,6 +887,7 @@ assign_stack_temp_for_type (enum machine
/* Create a new MEM rtx to avoid clobbering MEM flags of old slots. */
slot = gen_rtx_MEM (mode, XEXP (p->slot, 0));
+ set_mem_addr_space (slot, targetm.addr_space.for_frame ());
stack_slot_list = gen_rtx_EXPR_LIST (VOIDmode, slot, stack_slot_list);
/* If we know the alias set for the memory that will be used, use
@@ -2299,7 +2301,7 @@ assign_parms_augmented_arg_list (struct
&& ! cfun->returns_pcc_struct
&& targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
{
- tree type = build_pointer_type (TREE_TYPE (fntype));
+ tree type = build_pointer_type_in_frame (TREE_TYPE (fntype));
tree decl;
decl = build_decl (DECL_SOURCE_LOCATION (fndecl),
@@ -2381,7 +2383,7 @@ assign_parm_find_data_types (struct assi
if (pass_by_reference (&all->args_so_far_v, passed_mode,
passed_type, data->named_arg))
{
- passed_type = nominal_type = build_pointer_type (passed_type);
+ passed_type = nominal_type = build_pointer_type_in_frame (passed_type);
data->passed_pointer = true;
passed_mode = nominal_mode = TYPE_MODE (nominal_type);
}
===================================================================
@@ -1270,6 +1270,13 @@ initialize_argument_information (int num
if (!callee_copies && *ecf_flags & ECF_PURE)
*ecf_flags &= ~(ECF_PURE | ECF_LOOPING_CONST_OR_PURE);
+ addr_space_t as = MEM_ADDR_SPACE (copy);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ type
+ = build_qualified_type (type,
+ TYPE_QUALS_NO_ADDR_SPACE (type)
+ | ENCODE_QUAL_ADDR_SPACE (as));
+
args[i].tree_value
= build_fold_addr_expr_loc (loc, make_tree (type, copy));
type = TREE_TYPE (args[i].tree_value);
===================================================================
@@ -662,12 +662,13 @@ gen_frame_mem (enum machine_mode mode, r
rtx mem = gen_rtx_MEM (mode, addr);
MEM_NOTRAP_P (mem) = 1;
set_mem_alias_set (mem, get_frame_alias_set ());
+ set_mem_addr_space (mem, targetm.addr_space.for_frame ());
return mem;
}
/* Generate a MEM referring to a temporary use of the stack, not part
- of the fixed stack frame. For example, something which is pushed
- by a target splitter. */
+ of the fixed stack frame. For example, something which is pushed
+ by a target splitter. */
rtx
gen_tmp_stack_mem (enum machine_mode mode, rtx addr)
{
===================================================================
@@ -850,6 +850,7 @@ expand_one_stack_var_at (tree decl, rtx
x = plus_constant (Pmode, base, offset);
x = gen_rtx_MEM (DECL_MODE (SSAVAR (decl)), x);
+ set_mem_addr_space (x, targetm.addr_space.for_frame ());
if (TREE_CODE (decl) != SSA_NAME)
{
===================================================================
@@ -3205,9 +3205,14 @@ build_constant_desc (tree exp)
labelno = const_labelno++;
ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
+ tree type = TREE_TYPE (exp);
+ addr_space_t as = targetm.addr_space.for_global (true);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ type = build_qualified_type (type, (TYPE_QUALS_NO_ADDR_SPACE (type)
+ | ENCODE_QUAL_ADDR_SPACE (as)));
+
/* Construct the VAR_DECL associated with the constant. */
- decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label),
- TREE_TYPE (exp));
+ decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label), type);
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
TREE_READONLY (decl) = 1;
@@ -3244,6 +3249,7 @@ build_constant_desc (tree exp)
rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
set_mem_attributes (rtl, exp, 1);
+ set_mem_addr_space (rtl, as);
set_mem_alias_set (rtl, 0);
set_mem_alias_set (rtl, const_alias_set);
===================================================================
@@ -46,6 +46,7 @@ Software Foundation, 51 Franklin Street,
#include "tree-pass.h"
#include "gimple-pretty-print.h"
#include "cfgloop.h"
+#include "target.h"
/* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
type in the GIMPLE type system that is language-independent? */
@@ -1043,6 +1044,14 @@ build_one_array (gimple swtch, int num,
default_type = TREE_TYPE (info->default_values[num]);
value_type = array_value_type (swtch, default_type, num, info);
+ addr_space_t as = targetm.addr_space.for_global (true);
+ if (!ADDR_SPACE_GENERIC_P (as))
+ {
+ value_type
+ = build_qualified_type (value_type,
+ TYPE_QUALS_NO_ADDR_SPACE (value_type)
+ | ENCODE_QUAL_ADDR_SPACE (as));
+ }
array_type = build_array_type (value_type, arr_index_type);
if (default_type != value_type)
{
===================================================================
@@ -369,7 +369,8 @@ enum cv_qualifier {
TYPE_QUAL_CONST = 0x1,
TYPE_QUAL_VOLATILE = 0x2,
TYPE_QUAL_RESTRICT = 0x4,
- TYPE_QUAL_ATOMIC = 0x8
+ TYPE_QUAL_ATOMIC = 0x8,
+ TYPE_QUAL_AS_IMPLICIT = 0x10
};
/* Enumerate visibility settings. */
@@ -746,7 +747,8 @@ struct GTY(()) tree_base {
unsigned user_align : 1;
unsigned nameless_flag : 1;
unsigned atomic_flag : 1;
- unsigned spare0 : 3;
+ unsigned as_implicit_flag : 1;
+ unsigned spare0 : 2;
unsigned spare1 : 8;