Commit 82e9d970 by Philip Blundell Committed by Nick Clifton

Apply Philip Blundell's patch to fix PIC operands.

From-SVN: r31867
parent 2387c1d4
2000-02-09 Philip Blundell <pb@futuretv.com>
* config/arm/arm.c (legitimize_pic_address): Handle LABEL_REF
correctly.
* config/arm/arm.h (LEGITIMATE_CONSTANT_P): Allow anything when
generating PIC.
(LEGITIMATE_PIC_OPERAND): Disallow references to labels.
2000-02-09 Zack Weinberg <zack@wolery.cumb.org> 2000-02-09 Zack Weinberg <zack@wolery.cumb.org>
* cpplib.c (cpp_define, cpp_undef): Make sure the stacked buffer * cpplib.c (cpp_define, cpp_undef): Make sure the stacked buffer
......
...@@ -1476,6 +1476,181 @@ arm_return_in_memory (type) ...@@ -1476,6 +1476,181 @@ arm_return_in_memory (type)
return 1; return 1;
} }
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is NULL. */
void
arm_init_cumulative_args (pcum, fntype, libname, indirect)
CUMULATIVE_ARGS * pcum;
tree fntype;
rtx libname ATTRIBUTE_UNUSED;
int indirect ATTRIBUTE_UNUSED;
{
/* On the ARM, the offset starts at 0. */
pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype)))
? 1 : 0);
pcum->call_cookie = CALL_NORMAL;
if (TARGET_LONG_CALLS)
pcum->call_cookie = CALL_LONG;
/* Check for long call/short call attributes. The attributes
override any command line option. */
if (fntype)
{
if (lookup_attribute ("short_call", TYPE_ATTRIBUTES (fntype)))
pcum->call_cookie = CALL_SHORT;
else if (lookup_attribute ("long_call", TYPE_ATTRIBUTES (fntype)))
pcum->call_cookie = CALL_LONG;
}
}
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
MODE is the argument's machine mode.
TYPE is the data type of the argument (as a tree).
This is null for libcalls where that information may
not be available.
CUM is a variable of type CUMULATIVE_ARGS which gives info about
the preceding args and about the function being called.
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
rtx
arm_function_arg (pcum, mode, type, named)
CUMULATIVE_ARGS * pcum;
enum machine_mode mode;
tree type ATTRIBUTE_UNUSED;
int named;
{
if (mode == VOIDmode)
/* Compute operand 2 of the call insn. */
return GEN_INT (pcum->call_cookie);
if (! named || pcum->nregs >= NUM_ARG_REGS)
return NULL_RTX;
return gen_rtx_REG (mode, pcum->nregs);
}
/* Return 1 if the operand is a SYMBOL_REF for a function known to be in
this file. */
static int
current_file_function_operand (sym_ref)
rtx sym_ref;
{
return (SYMBOL_REF_FLAG (sym_ref)
|| sym_ref == XEXP (DECL_RTL (current_function_decl), 0));
}
/* Return non-zero if a 32 bit "long call" should be generated for this
call.
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. */
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) || TARGET_LONG_CALLS;
}
/* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific
attribute for TYPE. The attributes in ATTRIBUTES have previously been
assigned to TYPE. */
int
arm_valid_type_attribute_p (type, attributes, identifier, args)
tree type;
tree attributes ATTRIBUTE_UNUSED;
tree identifier;
tree args;
{
if ( TREE_CODE (type) != FUNCTION_TYPE
&& TREE_CODE (type) != METHOD_TYPE
&& TREE_CODE (type) != FIELD_DECL
&& TREE_CODE (type) != TYPE_DECL)
return 0;
/* Function calls made to this symbol must be done indirectly, because
it may lie outside of the 26 bit addressing range of a normal function
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))
return (args == NULL_TREE);
return 0;
}
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
int
arm_comp_type_attributes (type1, type2)
tree type1;
tree type2;
{
int l1, l2, s1, s2;
/* Check for mismatch of non-default calling convention. */
if (TREE_CODE (type1) != FUNCTION_TYPE)
return 1;
/* Check for mismatched call attributes. */
l1 = ! lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1));
l2 = ! lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2));
s1 = ! lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1));
s2 = ! lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2));
return ! ((l1 ^ l2) || (s1 ^s2) || (l1 | s2) || (s1 | l2));
}
int int
legitimate_pic_operand_p (x) legitimate_pic_operand_p (x)
rtx x; rtx x;
...@@ -1590,7 +1765,20 @@ legitimize_pic_address (orig, mode, reg) ...@@ -1590,7 +1765,20 @@ legitimize_pic_address (orig, mode, reg)
return gen_rtx_PLUS (Pmode, base, offset); return gen_rtx_PLUS (Pmode, base, offset);
} }
else if (GET_CODE (orig) == LABEL_REF) else if (GET_CODE (orig) == LABEL_REF)
current_function_uses_pic_offset_table = 1; {
current_function_uses_pic_offset_table = 1;
if (NEED_GOT_RELOC)
{
rtx pic_ref, address = gen_reg_rtx (Pmode);
emit_insn (gen_pic_load_addr (address, orig));
pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
emit_move_insn (address, pic_ref);
return address;
}
}
return orig; return orig;
} }
......
/* Definitions of target machine for GNU compiler, for ARM. /* Definitions of target machine for GNU compiler, for ARM.
Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc. Copyright (C) 1991, 93, 94, 05, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk). and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com) More major hacks by Richard Earnshaw (rearnsha@arm.com)
...@@ -48,7 +48,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -48,7 +48,7 @@ Boston, MA 02111-1307, USA. */
#define TARGET_CPU_strongarm1100 0x0040 #define TARGET_CPU_strongarm1100 0x0040
#define TARGET_CPU_arm9 0x0080 #define TARGET_CPU_arm9 0x0080
#define TARGET_CPU_arm9tdmi 0x0080 #define TARGET_CPU_arm9tdmi 0x0080
/* Configure didn't specify */ /* Configure didn't specify. */
#define TARGET_CPU_generic 0x8000 #define TARGET_CPU_generic 0x8000
enum arm_cond_code enum arm_cond_code
...@@ -365,7 +365,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -365,7 +365,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Generate re-entrant, PIC code" }, \ "Generate re-entrant, PIC code" }, \
{"no-apcs-reentrant", -ARM_FLAG_APCS_REENT, "" }, \ {"no-apcs-reentrant", -ARM_FLAG_APCS_REENT, "" }, \
{"alignment-traps", ARM_FLAG_MMU_TRAPS, \ {"alignment-traps", ARM_FLAG_MMU_TRAPS, \
"The MMU will trap on unaligned accesses" },\ "The MMU will trap on unaligned accesses" }, \
{"no-alignment-traps", -ARM_FLAG_MMU_TRAPS, "" }, \ {"no-alignment-traps", -ARM_FLAG_MMU_TRAPS, "" }, \
{"short-load-bytes", ARM_FLAG_MMU_TRAPS, "" }, \ {"short-load-bytes", ARM_FLAG_MMU_TRAPS, "" }, \
{"no-short-load-bytes", -ARM_FLAG_MMU_TRAPS, "" }, \ {"no-short-load-bytes", -ARM_FLAG_MMU_TRAPS, "" }, \
...@@ -385,7 +385,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -385,7 +385,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Support calls between THUMB and ARM instructions sets" }, \ "Support calls between THUMB and ARM instructions sets" }, \
{"no-thumb-interwork", -ARM_FLAG_INTERWORK, "" }, \ {"no-thumb-interwork", -ARM_FLAG_INTERWORK, "" }, \
{"abort-on-noreturn", ARM_FLAG_ABORT_NORETURN, \ {"abort-on-noreturn", ARM_FLAG_ABORT_NORETURN, \
"Generate a call to abort if a noreturn function returns"}, \ "Generate a call to abort if a noreturn function returns"},\
{"no-abort-on-noreturn", -ARM_FLAG_ABORT_NORETURN, ""}, \ {"no-abort-on-noreturn", -ARM_FLAG_ABORT_NORETURN, ""}, \
{"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, \ {"sched-prolog", -ARM_FLAG_NO_SCHED_PRO, \
"Do not move instructions into a function's prologue" }, \ "Do not move instructions into a function's prologue" }, \
...@@ -394,7 +394,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -394,7 +394,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
"Do not load the PIC register in function prologues" }, \ "Do not load the PIC register in function prologues" }, \
{"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \ {"no-single-pic-base", -ARM_FLAG_SINGLE_PIC_BASE, "" }, \
{"long-calls", ARM_FLAG_LONG_CALLS, \ {"long-calls", ARM_FLAG_LONG_CALLS, \
"Generate all call instructions as indirect calls"}, \ "Generate all call instructions as indirect calls"}, \
{"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \ {"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
SUBTARGET_SWITCHES \ SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT, "" } \ {"", TARGET_DEFAULT, "" } \
...@@ -411,7 +411,7 @@ Unrecognized value in TARGET_CPU_DEFAULT. ...@@ -411,7 +411,7 @@ Unrecognized value in TARGET_CPU_DEFAULT.
{"fp=", & target_fp_name, \ {"fp=", & target_fp_name, \
"Specify the version of the floating point emulator" }, \ "Specify the version of the floating point emulator" }, \
{ "structure-size-boundary=", & structure_size_string, \ { "structure-size-boundary=", & structure_size_string, \
"Specify the minumum bit alignment of structures" }, \ "Specify the minimum bit alignment of structures" }, \
{ "pic-register=", & arm_pic_register_string, \ { "pic-register=", & arm_pic_register_string, \
"Specify the register to be used for PIC addressing" } \ "Specify the register to be used for PIC addressing" } \
} }
...@@ -1136,6 +1136,23 @@ enum reg_class ...@@ -1136,6 +1136,23 @@ enum reg_class
than a word, or if they contain elements offset from zero in the struct. */ than a word, or if they contain elements offset from zero in the struct. */
#define DEFAULT_PCC_STRUCT_RETURN 0 #define DEFAULT_PCC_STRUCT_RETURN 0
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
type `int' suffices and can hold the number of bytes of argument so far. */
typedef struct
{
/* This is the number of argument registers scanned so far. */
int nregs;
/* instructions on how to process this call. */
int call_cookie;
}
CUMULATIVE_ARGS;
/* Flags for the call_cookie field of CUMULATIVE_ARGS. */
#define CALL_NORMAL 0 /* No special processing. */
#define CALL_LONG 1 /* Always call indirect. */
#define CALL_SHORT 2 /* Never call indirect. */
/* Define where to put the arguments to a function. /* Define where to put the arguments to a function.
Value is zero to push the argument on the stack, Value is zero to push the argument on the stack,
or a hard register in which to store the argument. or a hard register in which to store the argument.
...@@ -1154,38 +1171,29 @@ enum reg_class ...@@ -1154,38 +1171,29 @@ enum reg_class
only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is
passed in the stack (function_prologue will indeed make it pass in the passed in the stack (function_prologue will indeed make it pass in the
stack if necessary). */ stack if necessary). */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
((NAMED) \ arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
? ((CUM) >= NUM_ARG_REGS ? 0 : gen_rtx_REG (MODE, CUM))\
: 0)
/* For an arg passed partly in registers and partly in memory, /* For an arg passed partly in registers and partly in memory,
this is the number of registers used. this is the number of registers used.
For args passed entirely in registers or entirely in memory, zero. */ For args passed entirely in registers or entirely in memory, zero. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
( NUM_ARG_REGS > (CUM) \ ( NUM_ARG_REGS > (CUM).nregs \
&& (NUM_ARG_REGS < ((CUM) + NUM_REGS2 (MODE, TYPE))) \ && (NUM_ARG_REGS < ((CUM).nregs + NUM_REGS2 (MODE, TYPE))) \
? NUM_ARG_REGS - (CUM) : 0) ? NUM_ARG_REGS - (CUM).nregs : 0)
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
type `int' suffices and can hold the number of bytes of argument so far.
On the ARM, this is the number of bytes of arguments scanned so far. */
#define CUMULATIVE_ARGS int
/* Initialize a variable CUM of type CUMULATIVE_ARGS /* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE. for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. For a library call, FNTYPE is 0.
On the ARM, the offset starts at 0. */ On the ARM, the offset starts at 0. */
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \ #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
((CUM) = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) ? 1 : 0)) arm_init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (INDIRECT))
/* Update the data in CUM to advance over an argument /* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE. of mode MODE and data type TYPE.
(TYPE is null for libcalls where that information may not be available.) */ (TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ #define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
(CUM) += NUM_REGS2 (MODE, TYPE) (CUM).nregs += NUM_REGS2 (MODE, TYPE)
/* 1 if N is a possible register number for function argument passing. /* 1 if N is a possible register number for function argument passing.
On the ARM, r0-r3 are used to pass args. */ On the ARM, r0-r3 are used to pass args. */
...@@ -1209,8 +1217,8 @@ enum reg_class ...@@ -1209,8 +1217,8 @@ enum reg_class
{ \ { \
extern int current_function_anonymous_args; \ extern int current_function_anonymous_args; \
current_function_anonymous_args = 1; \ current_function_anonymous_args = 1; \
if ((CUM) < NUM_ARG_REGS) \ if ((CUM).nregs < NUM_ARG_REGS) \
(PRETEND_SIZE) = (NUM_ARG_REGS - (CUM)) * UNITS_PER_WORD; \ (PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
} }
/* Generate assembly output for the start of a function. */ /* Generate assembly output for the start of a function. */
...@@ -1437,8 +1445,18 @@ enum reg_class ...@@ -1437,8 +1445,18 @@ enum reg_class
On the ARM, allow any integer (invalid ones are removed later by insn On the ARM, allow any integer (invalid ones are removed later by insn
patterns), nice doubles and symbol_refs which refer to the function's patterns), nice doubles and symbol_refs which refer to the function's
constant pool XXX. */ constant pool XXX.
#define LEGITIMATE_CONSTANT_P(X) (! label_mentioned_p (X))
When generating pic allow anything. */
#define LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X))
/* If we are referencing a function that is static or is known to be
in this file, make the SYMBOL_REF special. We can use this to indicate
that we can do direct call to that function. */
#define ARM_MARK_NEARBY_FUNCTION(decl) \
if (TREE_CODE (decl) == FUNCTION_DECL \
&& (TREE_ASM_WRITTEN (decl) || ! TREE_PUBLIC (decl))) \
SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; \
/* Symbols in the text segment can be accessed without indirecting via the /* 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 constant pool; it may take an extra binary operation, but this is still
...@@ -1457,6 +1475,13 @@ enum reg_class ...@@ -1457,6 +1475,13 @@ enum reg_class
? TREE_CST_RTL (decl) : DECL_RTL (decl)); \ ? TREE_CST_RTL (decl) : DECL_RTL (decl)); \
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \ SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
} \ } \
\
ARM_MARK_NEARBY_FUNCTION (decl) \
}
#else
#define ENCODE_SECTION_INFO(decl) \
{ \
ARM_MARK_NEARBY_FUNCTION (decl) \
} }
#endif #endif
...@@ -1875,16 +1900,30 @@ extern const char * arm_pic_register_string; ...@@ -1875,16 +1900,30 @@ extern const char * arm_pic_register_string;
/* We can't directly access anything that contains a symbol, /* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */ nor can we indirect via the constant pool. */
#define LEGITIMATE_PIC_OPERAND_P(X) \ #define LEGITIMATE_PIC_OPERAND_P(X) \
(! symbol_mentioned_p (X) \ ( ! symbol_mentioned_p (X) \
&& (! CONSTANT_POOL_ADDRESS_P (X) \ && ! label_mentioned_p (X) \
|| ! symbol_mentioned_p (get_pool_constant (X)))) && (! CONSTANT_POOL_ADDRESS_P (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 /* 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 whether data needs to be in the GOT or can be referenced via a GOT
offset. */ offset. */
extern int making_const_table; extern int making_const_table;
/* If defined, a C expression whose value is nonzero if IDENTIFIER
with arguments ARGS is a valid machine specific attribute for TYPE.
The attributes in ATTRIBUTES have previously been assigned to TYPE. */
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
(arm_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
/* If defined, a C expression whose value is zero if the attributes on
TYPE1 and TYPE2 are incompatible, one if they are compatible, and
two if they are nearly compatible (which causes a warning to be
generated). */
#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
(arm_comp_type_attributes (TYPE1, TYPE2))
/* Condition code information. */ /* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
......
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