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

long_calls, no_long_calls.

From-SVN: r32248
This commit is contained in:
Dmitri Makarov 2000-02-29 01:42:52 +00:00 committed by Nick Clifton
parent 8aacf01600
commit c27ba9120a
10 changed files with 404 additions and 107 deletions

View File

@ -1,3 +1,72 @@
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.

View File

@ -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

View File

@ -40,19 +40,13 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "recog.h"
#include "ggc.h"
#include "arm-protos.h"
/* The maximum number of insns skipped which will be conditionalised if
possible. */
static int max_insns_skipped = 5;
extern FILE * asm_out_file;
/* Some function declarations. */
#include "tm_p.h"
#ifndef Mmode
#define Mmode enum machine_mode
#endif
/* Some function declarations. */
static HOST_WIDE_INT int_log2 PARAMS ((HOST_WIDE_INT));
static char * output_multi_immediate PARAMS ((rtx *, char *, char *, int, HOST_WIDE_INT));
static int arm_gen_constant PARAMS ((enum rtx_code, Mmode, HOST_WIDE_INT, rtx, rtx, int, int));
@ -76,6 +70,12 @@ static enum arm_cond_code get_arm_condition_code PARAMS ((rtx));
static int const_ok_for_op PARAMS ((HOST_WIDE_INT, enum rtx_code));
static void arm_add_gc_roots PARAMS ((void));
/* The maximum number of insns skipped which will be conditionalised if
possible. */
static int max_insns_skipped = 5;
extern FILE * asm_out_file;
/* True if we are currently building a constant table. */
int making_const_table;
@ -1487,9 +1487,8 @@ arm_init_cumulative_args (pcum, fntype, libname, indirect)
int indirect ATTRIBUTE_UNUSED;
{
/* On the ARM, the offset starts at 0. */
pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype)))
? 1 : 0);
pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);
pcum->call_cookie = CALL_NORMAL;
if (TARGET_LONG_CALLS)
@ -1534,73 +1533,37 @@ arm_function_arg (pcum, mode, type, named)
return gen_rtx_REG (mode, pcum->nregs);
}
/* Return 1 if the operand is a SYMBOL_REF for a function
known to be defined in the current compilation unit. */
static int
current_file_function_operand (sym_ref)
rtx sym_ref;
/* Encode the current state of the #pragma [no_]long_calls. */
typedef enum
{
/* XXX FIXME - we need some way to determine if SYMREF has already been
compiled. We wanted to used SYMBOL_REF_FLAG but this is already in use
by the constant pool generation code. */
return
GET_CODE (sym_ref) == SYMBOL_REF
&& sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
&& ! DECL_WEAK (current_function_decl);
}
OFF, /* No #pramgma [no_]long_calls is in effect. */
LONG, /* #pragma long_calls is in effect. */
SHORT /* #pragma no_long_calls is in effect. */
} arm_pragma_enum;
/* Return non-zero if a 32 bit "long call" should be generated for this
call.
static arm_pragma_enum arm_pragma_long_calls = OFF;
We generate a long call if the function is not declared
__attribute__ ((short_call),
AND:
(1) the function is declared __attribute__ ((long_call))
OR
(2) -mlong-calls is enabled and we don't know whether the target
function is declared in this file.
This function will typically be called by C fragments in the machine
description file. CALL_REF is the matched rtl operand. CALL_COOKIE
describes the value of the long_call and short_call attributes for
the called functiion. CALL_SYMBOL is used to distinguish between
two different callers of the function. It is set to 1 in the "call_symbol"
and "call_symbol_value" patterns in arm.md and to 0 in the "call" and
"call_value" patterns. This is because of the difference of SYM_REFs passed
from "call_symbol" and "call" patterns. */
/* Handle pragmas for compatibility with Intel's compilers.
FIXME: This is incomplete, since it does not handle all
the pragmas that the Intel compilers understand. */
int
arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
rtx sym_ref;
int call_cookie;
int call_symbol;
arm_process_pragma (p_getc, p_ungetc, pname)
int (* p_getc) PARAMS ((void)) ATTRIBUTE_UNUSED;
void (* p_ungetc) PARAMS ((int)) ATTRIBUTE_UNUSED;
char * pname;
{
if (! call_symbol)
{
if (GET_CODE (sym_ref) != MEM)
return 0;
sym_ref = XEXP (sym_ref, 0);
}
if (GET_CODE (sym_ref) != SYMBOL_REF)
return 0;
if (call_cookie & CALL_SHORT)
return 0;
if (TARGET_LONG_CALLS && flag_function_sections)
return 1;
if (current_file_function_operand (sym_ref, VOIDmode))
/* Should be pragma 'far' or equivalent for callx/balx here. */
if (strcmp (pname, "long_calls") == 0)
arm_pragma_long_calls = LONG;
else if (strcmp (pname, "no_long_calls") == 0)
arm_pragma_long_calls = SHORT;
else if (strcmp (pname, "long_calls_off") == 0)
arm_pragma_long_calls = OFF;
else
return 0;
return (call_cookie & CALL_LONG) || TARGET_LONG_CALLS;
return 1;
}
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
@ -1624,7 +1587,7 @@ arm_valid_type_attribute_p (type, attributes, identifier, args)
call. */
if (is_attribute_p ("long_call", identifier))
return (args == NULL_TREE);
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
if (is_attribute_p ("short_call", identifier))
@ -1668,6 +1631,136 @@ arm_comp_type_attributes (type1, type2)
return 1;
}
/* Encode long_call or short_call attribute by prefixing
symbol name in DECL with a special character FLAG. */
void
arm_encode_call_attribute (decl, flag)
tree decl;
char flag;
{
char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
int len = strlen (str);
char * newstr;
if (TREE_CODE (decl) != FUNCTION_DECL)
return;
/* Do not allow weak functions to be treated as short call. */
if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
return;
if (ggc_p)
newstr = ggc_alloc_string (NULL, len + 2);
else
newstr = permalloc (len + 2);
sprintf (newstr, "%c%s", flag, str);
XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
}
/* Assigns default attributes to newly defined type. This is used to
set short_call/long_call attributes for function types of
functions defined inside corresponding #pragma scopes. */
void
arm_set_default_type_attributes (type)
tree type;
{
/* Add __attribute__ ((long_call)) to all functions, when
inside #pragma long_calls or __attribute__ ((short_call)),
when inside #pragma no_long_calls. */
if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
tree type_attr_list, attr_name;
type_attr_list = TYPE_ATTRIBUTES (type);
if (arm_pragma_long_calls == LONG)
attr_name = get_identifier ("long_call");
else if (arm_pragma_long_calls == SHORT)
attr_name = get_identifier ("short_call");
else
return;
type_attr_list = tree_cons (attr_name, NULL_TREE, type_attr_list);
TYPE_ATTRIBUTES (type) = type_attr_list;
}
}
/* Return 1 if the operand is a SYMBOL_REF for a function known to be
defined within the current compilation unit. If this caanot be
determined, then 0 is returned. */
static int
current_file_function_operand (sym_ref)
rtx sym_ref;
{
/* This is a bit of a fib. A function will have a short call flag
applied to its name if it has the short call attribute, or it has
already been defined within the current compilation unit. */
if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
return 1;
/* The current funciton is always defined within the current compilation
unit. if it s a weak defintion however, then this may not be the real
defintion of the function, and so we have to say no. */
if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
&& ! DECL_WEAK (current_function_decl))
return 1;
/* We cannot make the determination - default to returning 0. */
return 0;
}
/* Return non-zero if a 32 bit "long_call" should be generated for
this call. We generate a long_call if the function:
a. has an __attribute__((long call))
or b. is within the scope of a #pragma long_calls
or c. the -mlong-calls command line switch has been specified
However we do not generate a long call if the function:
d. has an __attribute__ ((short_call))
or e. is inside the scope of a #pragma no_long_calls
or f. has an __attribute__ ((section))
or g. is defined within the current compilation unit.
This function will be called by C fragments contained in the machine
description file. CALL_REF and CALL_COOKIE correspond to the matched
rtl operands. CALL_SYMBOL is used to distinguish between
two different callers of the function. It is set to 1 in the
"call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
and "call_value" patterns. This is because of the difference in the
SYM_REFs passed by these patterns. */
int
arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
rtx sym_ref;
int call_cookie;
int call_symbol;
{
if (! call_symbol)
{
if (GET_CODE (sym_ref) != MEM)
return 0;
sym_ref = XEXP (sym_ref, 0);
}
if (GET_CODE (sym_ref) != SYMBOL_REF)
return 0;
if (call_cookie & CALL_SHORT)
return 0;
if (TARGET_LONG_CALLS && flag_function_sections)
return 1;
if (current_file_function_operand (sym_ref, VOIDmode))
return 0;
return (call_cookie & CALL_LONG)
|| ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
|| TARGET_LONG_CALLS;
}
int
legitimate_pic_operand_p (x)
@ -6988,6 +7081,31 @@ arm_final_prescan_insn (insn)
}
}
/* Return the length of a function name prefix
that starts with the character 'c'. */
static int
arm_get_strip_length (char c)
{
switch (c)
{
ARM_NAME_ENCODING_LENGTHS
default: return 0;
}
}
/* Return a pointer to a function's name with any
and all prefix encodings stripped from it. */
const char *
arm_strip_name_encoding (const char * name)
{
int skip;
while ((skip = arm_get_strip_length (* name)))
name += skip;
return name;
}
#ifdef AOF_ASSEMBLER
/* Special functions only needed when producing AOF syntax assembler. */

View File

@ -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,

View File

@ -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\";

View File

@ -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]; \

View File

@ -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

View File

@ -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)); \

View File

@ -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

View File

@ -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.