bfin.c (bfin_expand_call): Inline PLT with l1_text attribute when appropriate.
* config/bfin/bfin.c (bfin_expand_call): Inline PLT with l1_text attribute when appropriate. (bfin_handle_l1_text_attribute): New. (bfin_handle_l1_data_attribute): New. (bfin_attribute_table): Add attributes: l1_text, l1_data, l1_data_A and l1_data_B. * doc/extend.texi (node Function Attributes): Document l1_text function attribute. (Variable Attributes): Add Blackfin subsection. Document l1_data, l1_data_A and l1_data_B variable attributes. From-SVN: r127887
This commit is contained in:
parent
e874e49fdf
commit
4af797b502
@ -1,3 +1,16 @@
|
|||||||
|
2007-08-29 Jie Zhang <jie.zhang@analog.com>
|
||||||
|
|
||||||
|
* config/bfin/bfin.c (bfin_expand_call): Inline PLT with l1_text
|
||||||
|
attribute when appropriate.
|
||||||
|
(bfin_handle_l1_text_attribute): New.
|
||||||
|
(bfin_handle_l1_data_attribute): New.
|
||||||
|
(bfin_attribute_table): Add attributes: l1_text, l1_data,
|
||||||
|
l1_data_A and l1_data_B.
|
||||||
|
* doc/extend.texi (node Function Attributes): Document l1_text
|
||||||
|
function attribute.
|
||||||
|
(Variable Attributes): Add Blackfin subsection. Document l1_data,
|
||||||
|
l1_data_A and l1_data_B variable attributes.
|
||||||
|
|
||||||
2007-08-28 Jie Zhang <jie.zhang@analog.com>
|
2007-08-28 Jie Zhang <jie.zhang@analog.com>
|
||||||
|
|
||||||
* config/bfin/bfin.opt (minline-plt): Add.
|
* config/bfin/bfin.opt (minline-plt): Add.
|
||||||
|
@ -1879,11 +1879,30 @@ bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
|
|||||||
|
|
||||||
if (TARGET_FDPIC)
|
if (TARGET_FDPIC)
|
||||||
{
|
{
|
||||||
|
int caller_has_l1_text, callee_has_l1_text;
|
||||||
|
|
||||||
|
caller_has_l1_text = callee_has_l1_text = 0;
|
||||||
|
|
||||||
|
if (lookup_attribute ("l1_text",
|
||||||
|
DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
|
||||||
|
caller_has_l1_text = 1;
|
||||||
|
|
||||||
|
if (GET_CODE (callee) == SYMBOL_REF
|
||||||
|
&& SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
|
||||||
|
&& lookup_attribute
|
||||||
|
("l1_text",
|
||||||
|
DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
|
||||||
|
callee_has_l1_text = 1;
|
||||||
|
|
||||||
if (GET_CODE (callee) != SYMBOL_REF
|
if (GET_CODE (callee) != SYMBOL_REF
|
||||||
|| bfin_longcall_p (callee, INTVAL (cookie))
|
|| bfin_longcall_p (callee, INTVAL (cookie))
|
||||||
|| (GET_CODE (callee) == SYMBOL_REF
|
|| (GET_CODE (callee) == SYMBOL_REF
|
||||||
&& !SYMBOL_REF_LOCAL_P (callee)
|
&& !SYMBOL_REF_LOCAL_P (callee)
|
||||||
&& TARGET_INLINE_PLT))
|
&& TARGET_INLINE_PLT)
|
||||||
|
|| caller_has_l1_text != callee_has_l1_text
|
||||||
|
|| (caller_has_l1_text && callee_has_l1_text
|
||||||
|
&& (GET_CODE (callee) != SYMBOL_REF
|
||||||
|
|| !SYMBOL_REF_LOCAL_P (callee))))
|
||||||
{
|
{
|
||||||
rtx addr = callee;
|
rtx addr = callee;
|
||||||
if (! address_operand (addr, Pmode))
|
if (! address_operand (addr, Pmode))
|
||||||
@ -4646,6 +4665,91 @@ bfin_handle_longcall_attribute (tree *node, tree name,
|
|||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle a "l1_text" attribute; arguments as in
|
||||||
|
struct attribute_spec.handler. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
|
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||||
|
{
|
||||||
|
tree decl = *node;
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
|
{
|
||||||
|
error ("`%s' attribute only applies to functions",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The decl may have already been given a section attribute
|
||||||
|
from a previous declaration. Ensure they match. */
|
||||||
|
else if (DECL_SECTION_NAME (decl) != NULL_TREE
|
||||||
|
&& strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
|
||||||
|
".l1.text") != 0)
|
||||||
|
{
|
||||||
|
error ("section of %q+D conflicts with previous declaration",
|
||||||
|
decl);
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
|
||||||
|
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
|
||||||
|
arguments as in struct attribute_spec.handler. */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|
||||||
|
int ARG_UNUSED (flags), bool *no_add_attrs)
|
||||||
|
{
|
||||||
|
tree decl = *node;
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) != VAR_DECL)
|
||||||
|
{
|
||||||
|
error ("`%s' attribute only applies to variables",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else if (current_function_decl != NULL_TREE
|
||||||
|
&& !TREE_STATIC (decl))
|
||||||
|
{
|
||||||
|
error ("`%s' attribute cannot be specified for local variables",
|
||||||
|
IDENTIFIER_POINTER (name));
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *section_name;
|
||||||
|
|
||||||
|
if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
|
||||||
|
section_name = ".l1.data";
|
||||||
|
else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
|
||||||
|
section_name = ".l1.data.A";
|
||||||
|
else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
|
||||||
|
section_name = ".l1.data.B";
|
||||||
|
else
|
||||||
|
gcc_unreachable ();
|
||||||
|
|
||||||
|
/* The decl may have already been given a section attribute
|
||||||
|
from a previous declaration. Ensure they match. */
|
||||||
|
if (DECL_SECTION_NAME (decl) != NULL_TREE
|
||||||
|
&& strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
|
||||||
|
section_name) != 0)
|
||||||
|
{
|
||||||
|
error ("section of %q+D conflicts with previous declaration",
|
||||||
|
decl);
|
||||||
|
*no_add_attrs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DECL_SECTION_NAME (decl)
|
||||||
|
= build_string (strlen (section_name) + 1, section_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL_TREE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table of valid machine attributes. */
|
/* Table of valid machine attributes. */
|
||||||
const struct attribute_spec bfin_attribute_table[] =
|
const struct attribute_spec bfin_attribute_table[] =
|
||||||
{
|
{
|
||||||
@ -4658,6 +4762,10 @@ const struct attribute_spec bfin_attribute_table[] =
|
|||||||
{ "saveall", 0, 0, false, true, true, NULL },
|
{ "saveall", 0, 0, false, true, true, NULL },
|
||||||
{ "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
|
{ "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
|
||||||
{ "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
|
{ "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
|
||||||
|
{ "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
|
||||||
|
{ "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
|
||||||
|
{ "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
|
||||||
|
{ "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
|
||||||
{ NULL, 0, 0, false, false, false, NULL }
|
{ NULL, 0, 0, false, false, false, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2148,6 +2148,13 @@ When used together with @code{interrupt_handler}, @code{exception_handler}
|
|||||||
or @code{nmi_handler}, code will be generated to load the stack pointer
|
or @code{nmi_handler}, code will be generated to load the stack pointer
|
||||||
from the USP register in the function prologue.
|
from the USP register in the function prologue.
|
||||||
|
|
||||||
|
@item l1_text
|
||||||
|
@cindex @code{l1_text} function attribute
|
||||||
|
This attribute specifies a function to be placed into L1 Instruction
|
||||||
|
SRAM. The function will be put into a specific section named @code{.l1.text}.
|
||||||
|
With @option{-mfdpic}, function calls with a such function as the callee
|
||||||
|
or caller will use inlined PLT.
|
||||||
|
|
||||||
@item long_call/short_call
|
@item long_call/short_call
|
||||||
@cindex indirect calls on ARM
|
@cindex indirect calls on ARM
|
||||||
This attribute specifies how a particular function is called on
|
This attribute specifies how a particular function is called on
|
||||||
@ -3465,6 +3472,24 @@ The @code{dllexport} attribute is described in @xref{Function Attributes}.
|
|||||||
|
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@subsection Blackfin Variable Attributes
|
||||||
|
|
||||||
|
Three attributes are currently defined for the Blackfin.
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item l1_data
|
||||||
|
@item l1_data_A
|
||||||
|
@item l1_data_B
|
||||||
|
@cindex @code{l1_data} variable attribute
|
||||||
|
@cindex @code{l1_data_A} variable attribute
|
||||||
|
@cindex @code{l1_data_B} variable attribute
|
||||||
|
Use these attributes on the Blackfin to place the variable into L1 Data SRAM.
|
||||||
|
Variables with @code{l1_data} attribute will be put into the specific section
|
||||||
|
named @code{.l1.data}. Those with @code{l1_data_A} attribute will be put into
|
||||||
|
the specific section named @code{.l1.data.A}. Those with @code{l1_data_B}
|
||||||
|
attribute will be put into the specific section named @code{.l1.data.B}.
|
||||||
|
@end table
|
||||||
|
|
||||||
@subsection M32R/D Variable Attributes
|
@subsection M32R/D Variable Attributes
|
||||||
|
|
||||||
One attribute is currently defined for the M32R/D@.
|
One attribute is currently defined for the M32R/D@.
|
||||||
|
Loading…
Reference in New Issue
Block a user