Commit c27ba912 by Dmitri Makarov Committed by Nick Clifton

Apply Dimitri Makarov's patch to import attribute short_call and #pragma

long_calls, no_long_calls.

From-SVN: r32248
parent 8aacf016
2000-02-28 Dmitri Makarov <dim@windriver.com>
* extend.texi: Document ARM's support for long/short calls.
* invoke.texi: Document ARM's -mlong-calls command line switch.
* config/arm/arm-protos.h (arm_is_longcall_p): Add prototype.
(arm_encode_call_attribute): Add prototype.
(arm_set_default_type_attribute): Add prototype.
(arm_strip_name_encoding): Add prototype.
* config/arm/arm.c (arm_init_cumulative_args): replace
initialisation og 'long_calls' field with initialisation of
'call_cookie' field.
(enum arm_pragma_enum): New enum.
(arm_pragma_long_calls): New static variable.
(arm_process_pragma): Also process "#pragma long_calls_off".
(arm_valid_type_attribute_p): Accept short_call attribute.
(arm_comp_type_attributes): Check long/short call attributes.
(arm_encode_call_attribute): New function: Encode long_call
or short_call attribute in function name.
(arm_set_default_type_attributes): New function: Assign
default attributes to newly defined type.
(current_file_function_operand): New function: Return true if
the symbol is a function which has already been compiled.
(arm_is_longcall_p): New function: Return true if the
indicated function should be called via a long call.
(arm_get_strip_length): New function. Returns number of
prefix characters to be stripped from a function's name.
(arm_strip_name_encoding): New function. Strip prefix characters
from a function's name.
* config/arm/arm.h (CUMULATIVE_ARGS): Replace 'long_call' field
with 'call_cookie'.
(SHORT_CALL_FAG_CHAR): Define.
(LONG_CALL_FAG_CHAR): Define.
(ENCODED_SHORT_CALL_ATTR_P): Define.
(ENCODED_LONG_CALL_ATTR_P): Define.
(ARM_NAME_ENCODING_LENGTHS): Define.
(STRIP_NAME_ENCODING): Define.
(ASM_OUTPUT_LABELREF): Define, and use to strip name encoding.
(ARM_ENCODE_CALL_TYPE): Define.
(ENCODE_SECTION): Invoke ARM_ENCODE_CALL_TYPE.
(ARM_DECLARE_FUNCTION_SIZE): Define.
(SET_DEFAULT_TYPE_ATTRIBUTES): Define.
* config/arm/arm.md (call): Call arm_is_longcall_p to decide
if a long call is needed.
(call_value): Ditto.
(call_symbol): Ditto.
* config/arm/elf.h (ASM_DECLARE_FUNCTION_SIZE): Add invocation of
ARM_DECLARE_FUNCTION_SIZE.
* config/arm/pe.h (ARM_PE_FLAG_CHAR): Define.
(SUBTARGET_NAME_ENCODING_LENGTHS): Define.
(ARM_STRIP_NAME_ENCODING): Undefine.
(STRIP_NAME_ENCODING): Undefine.
(ASM_OUTPUT_LABELREF): Use arm_strip_name_encoding.
(ASM_DECLARE_FUNCTION_NAME): Ditto.
(ASM_OUTPUT_COMMON): Ditto.
(ASM_DECLARE_OBJECT_NAME): Ditto.
* config/arm/pe.c (arm_dllexport_name_p): Check for
ARM_PE_FLAG_CHAR.
(arm_dllimport_name_p): Ditto.
(arm_mark_dllexport): Use ARM_PE_FLAG_CHAR.
(arm_mark_dllimport): Ditto.
Mon Feb 28 22:11:12 2000 J"orn Rennecke <amylaar@cygnus.co.uk>
* sh.h (DWARF_LINE_MIN_INSTR_LENGTH): Define.
......
......@@ -34,6 +34,7 @@ extern void output_ascii_pseudo_op PARAMS ((FILE *, unsigned char *, int));
extern void output_func_epilogue PARAMS ((int));
extern void output_func_prologue PARAMS ((FILE *, int));
extern int use_return_insn PARAMS ((int));
extern const char * arm_strip_name_encoding PARAMS ((const char *));
#if defined AOF_ASSEMBLER
extern void aof_add_import PARAMS ((char *));
extern char * aof_data_section PARAMS ((void));
......@@ -62,6 +63,9 @@ extern void arm_pe_encode_section_info PARAMS ((tree));
extern tree arm_pe_merge_machine_decl_attributes PARAMS ((tree, tree));
extern void arm_pe_unique_section PARAMS ((tree, int));
extern int arm_pe_valid_machine_decl_attribute PARAMS ((tree, tree, tree, tree));
extern void arm_set_default_type_attributes PARAMS ((tree));
extern void arm_encode_call_attribute PARAMS ((tree, char));
extern int arm_pe_return_in_memory PARAMS ((tree));
#endif
#ifdef RTX_CODE
......
......@@ -397,7 +397,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Do not load the PIC register in function prologues" }, \
{"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \
{"long-calls", ARM_FLAG_LONG_CALLS, \
"Generate all call instructions as indirect calls"}, \
"Generate call insns as indirect calls, if necessary"}, \
{"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT, "" } \
......@@ -1037,7 +1037,7 @@ enum reg_class
else \
break; \
\
high = ((((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000); \
high = ((((val - low) & 0xffffffffUL) ^ 0x80000000UL) - 0x80000000UL);\
/* Check for overflow or zero */ \
if (low == 0 || high == 0 || (high + low != val)) \
break; \
......@@ -1452,6 +1452,55 @@ CUMULATIVE_ARGS;
When generating pic allow anything. */
#define LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X))
/* Special characters prefixed to function names
in order to encode attribute like information.
Note, '@' and '*' have already been taken. */
#define SHORT_CALL_FLAG_CHAR '^'
#define LONG_CALL_FLAG_CHAR '#'
#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
(*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME) \
(*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
#ifndef SUBTARGET_NAME_ENCODING_LENGTHS
#define SUBTARGET_NAME_ENCODING_LENGTHS
#endif
/* This is a C fragement for the inside of a switch statement.
Each case label should return the number of characters to
be stripped from the start of a function's name, if that
name starts with the indicated character. */
#define ARM_NAME_ENCODING_LENGTHS \
case SHORT_CALL_FLAG_CHAR: return 1; \
case LONG_CALL_FLAG_CHAR: return 1; \
case '*': return 1; \
SUBTARGET_NAME_ENCODING_LENGTHS
/* This has to be handled by a function because more than part of the
ARM backend uses funciton name prefixes to encode attributes. */
#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
(VAR) = arm_strip_name_encoding (SYMBOL_NAME)
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
fprintf (FILE, "%s%s", USER_LABEL_PREFIX, arm_strip_name_encoding (NAME))
/* If we are referencing a function that is weak then encode a long call
flag in the function name, otherwise if the function is static or
or known to be defined in this file then encode a short call flag.
This macro is used inside the ENCODE_SECTION macro. */
#define ARM_ENCODE_CALL_TYPE(decl) \
if (TREE_CODE (decl) == FUNCTION_DECL) \
{ \
if (DECL_WEAK (decl)) \
arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
else if (! TREE_PUBLIC (decl)) \
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
} \
/* Symbols in the text segment can be accessed without indirecting via the
constant pool; it may take an extra binary operation, but this is still
......@@ -1470,9 +1519,18 @@ CUMULATIVE_ARGS;
? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
} \
ARM_ENCODE_CALL_TYPE (decl) \
}
#else
#define ENCODE_SECTION_INFO(decl) \
{ \
ARM_ENCODE_CALL_TYPE (decl) \
}
#endif
#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
We have two alternate definitions for each of them.
......@@ -1892,8 +1950,8 @@ extern const char * arm_pic_register_string;
( ! symbol_mentioned_p (X) \
&& ! label_mentioned_p (X) \
&& (! CONSTANT_POOL_ADDRESS_P (X) \
|| ( ! symbol_mentioned_p (get_pool_constant (X))) \
&& ! label_mentioned_p (get_pool_constant (X))))
|| ( ! symbol_mentioned_p (get_pool_constant (X)) \
&& ! label_mentioned_p (get_pool_constant (X)))))
/* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT
......@@ -1912,6 +1970,14 @@ extern int making_const_table;
generated). */
#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
(arm_comp_type_attributes (TYPE1, TYPE2))
/* If defined, a C statement that assigns default attributes to newly
defined TYPE. */
#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \
arm_set_default_type_attributes (TYPE)
/* Handle pragmas for compatibility with Intel's compilers. */
#define HANDLE_PRAGMA(GET, UNGET, NAME) arm_process_pragma (GET, UNGET, NAME)
/* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
......
......@@ -4514,18 +4514,24 @@
""
"
{
rtx callee = XEXP (operands[0], 0);
rtx callee;
/* Decide if we need to generate an indirect call by loading the 32 bit
address of the callee into a register and then jumping to the contents
of that register. operands[2] contains the long_call / short_call
attribute. The third parameter to arm_is_longcall_p tells it that it
is being passed a (MEM) and not a SYMREF(). */
/* In an untyped call, we can get NULL for operand 2. */
if (operands[2] == NULL_RTX)
operands[2] = const0_rtx;
/* This is to decide if we should generate indirect calls by loading the
32 bit address of the callee into a register before performing the
branch and link. operand[2] encodes the long_call/short_call
attribute of the function being called. This attribute is set whenever
__attribute__((long_call/short_call)) or #pragma long_call/no_long_call
is used, and the short_call attribute can also be set if function is
declared as static or if it has already been defined in the current
compilation unit. See arm.c and arm.h for info about this. The third
parameter to arm_is_longcall_p is used to tell it which pattern
invoked it. */
callee = XEXP (operands[0], 0);
if (GET_CODE (callee) != REG
&& arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
XEXP (operands[0], 0) = force_reg (Pmode, callee);
......@@ -4575,7 +4581,7 @@
/* See the comment in define_expand \"call\". */
if (GET_CODE (callee) != REG
&& arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
XEXP (operands[1], 0) = force_reg (Pmode, callee);
XEXP (operands[1], 0) = force_reg (Pmode, callee);
}"
)
......@@ -4613,8 +4619,8 @@
(match_operand:SI 1 "general_operand" "g"))
(use (match_operand 2 "" ""))
(clobber (reg:SI 14))]
"! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)
&& GET_CODE (operands[0]) == SYMBOL_REF"
"(GET_CODE (operands[0]) == SYMBOL_REF)
&& ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
"*
{
return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
......@@ -4627,8 +4633,8 @@
(match_operand:SI 2 "general_operand" "g")))
(use (match_operand 3 "" ""))
(clobber (reg:SI 14))]
"! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)
&& GET_CODE (operands[1]) == SYMBOL_REF"
"(GET_CODE (operands[1]) == SYMBOL_REF)
&& ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
"*
{
return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
......
......@@ -127,6 +127,7 @@ Boston, MA 02111-1307, USA. */
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do \
{ \
ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \
if (!flag_inhibit_size_directive) \
{ \
char label[256]; \
......
......@@ -19,9 +19,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "system.h"
#include "rtl.h"
#include "output.h"
#include "flags.h"
......@@ -240,7 +239,7 @@ int
arm_dllexport_name_p (symbol)
char * symbol;
{
return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.';
return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
}
/* Return non-zero if SYMBOL is marked as being dllimport'd. */
......@@ -249,7 +248,7 @@ int
arm_dllimport_name_p (symbol)
char * symbol;
{
return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.';
return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
}
/* Mark a DECL as being dllexport'd.
......@@ -278,7 +277,7 @@ arm_mark_dllexport (decl)
return; /* already done */
newname = alloca (strlen (oldname) + 4);
sprintf (newname, "@e.%s", oldname);
sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
......@@ -349,7 +348,7 @@ arm_mark_dllimport (decl)
}
newname = alloca (strlen (oldname) + 11);
sprintf (newname, "@i.__imp_%s", oldname);
sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
/* We pass newname through get_identifier to ensure it has a unique
address. RTL processing can sometimes peek inside the symbol ref
......
......@@ -19,6 +19,12 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#define ARM_PE_FLAG_CHAR '@'
/* Ensure that @x. will be stripped from the function name. */
#define SUBTARGET_NAME_ENCODING_LENGTHS \
case ARM_PE_FLAG_CHAR: return 3;
#include "arm/coff.h"
#undef USER_LABEL_PREFIX
......@@ -123,16 +129,6 @@ Boston, MA 02111-1307, USA. */
#define REDO_SECTION_INFO_P(DECL) 1
#endif
/* Utility used only in this file. */
#define ARM_STRIP_NAME_ENCODING(SYM_NAME) \
((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
/* Strip any text from SYM_NAME added by ENCODE_SECTION_INFO and store
the result in VAR. */
#undef STRIP_NAME_ENCODING
#define STRIP_NAME_ENCODING(VAR, SYM_NAME) \
(VAR) = ARM_STRIP_NAME_ENCODING (SYM_NAME)
/* Define this macro if in some cases global symbols from one translation
unit may not be bound to undefined symbols in another translation unit
without user intervention. For instance, under Microsoft Windows
......@@ -184,7 +180,7 @@ Boston, MA 02111-1307, USA. */
/* Output a reference to a label. */
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, ARM_STRIP_NAME_ENCODING (NAME))
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, arm_strip_name_encoding (NAME))
/* Output a function definition label. */
#undef ASM_DECLARE_FUNCTION_NAME
......@@ -195,7 +191,7 @@ Boston, MA 02111-1307, USA. */
{ \
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n",\
ARM_STRIP_NAME_ENCODING (NAME)); \
arm_strip_name_encoding (NAME)); \
function_section (DECL); \
} \
if (TARGET_POKE_FUNCTION_NAME) \
......@@ -213,7 +209,7 @@ Boston, MA 02111-1307, USA. */
{ \
drectve_section (); \
fprintf ((STREAM), "\t.ascii \" -export:%s\"\n",\
ARM_STRIP_NAME_ENCODING (NAME)); \
arm_strip_name_encoding (NAME)); \
} \
if (! arm_dllimport_name_p (NAME)) \
{ \
......@@ -235,7 +231,7 @@ Boston, MA 02111-1307, USA. */
enum in_section save_section = in_section; \
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n",\
ARM_STRIP_NAME_ENCODING (NAME)); \
arm_strip_name_encoding (NAME)); \
switch_to_section (save_section, (DECL)); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
......
......@@ -1613,6 +1613,17 @@ compiler to always call the function via a pointer, so that functions
which reside further than 64 megabytes (67,108,864 bytes) from the
current location can be called.
@item long_call/short_call
@cindex indirect calls on ARM
This attribute allows to specify how to call a particular function on
ARM. Both attributes override the @code{-mlong-calls} (@pxref{ARM Options})
command line switch and @code{#pragma long_calls} settings. The
@code{long_call} attribute causes the compiler to always call the
function by first loading its address into a register and then using the
contents of that register. The @code{short_call} attribute always places
the offset to the function from the call site into the @samp{BL}
instruction directly.
@item dllimport
@cindex functions which are imported from a dll on PowerPC Windows NT
On the PowerPC running Windows NT, the @code{dllimport} attribute causes
......
......@@ -269,6 +269,7 @@ in the following sections.
-mstructure-size-boundary=
-mbsd -mxopen -mno-symrename
-mabort-on-noreturn
-mlong-calls -mno-long-calls
-mnop-fun-dllimport -mno-nop-fun-dllimport
-msingle-pic-base -mno-single-pic-base
-mpic-register=
......@@ -4608,6 +4609,32 @@ value as future versions of the toolchain may default to this value.
Generate a call to the function abort at the end of a noreturn function.
It will be executed if the function tries to return.
@item -mlong-calls
@itemx -mno-long-calls
Tells the compiler to perform function calls by first loading the
address of the function into a register and then performing a subroutine
call on this register. This switch is needed if the target function
will lie outside of the 64 megabyte addressing range of the offset based
version of subroutine call instruction.
Even if this switch is enabled, not all function calls will be turned
into long calls. The heuristic is that static functions, functions
which have the @samp{short-call} attribute, functions that are inside
the scope of a @samp{#pragma no_long_calls} directive and functions whose
definitions have already been compiled within the current compilation
unit, will not be turned into long calls. The exception to this rule is
that weak function defintions, functions with the @samp{long-call}
attribute or the @samp{section} attribute, and functions that are within
the scope of a @samp{#pragma long_calls} directive, will always be
turned into long calls.
This feature is not enabled by default. Specifying
@samp{--no-long-calls} will restore the default behaviour, as will
placing the function calls within the scope of a @samp{#pragma
long_calls_off} directive. Note these switches have no effect on how
the compiler generates code to handle function calls via function
pointers.
@item -mnop-fun-dllimport
@kindex -mnop-fun-dllimport
Disable the support for the @emph{dllimport} attribute.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment