Commit 6a4cee5f by Michael Meissner

Add attribute((longcall)) support

From-SVN: r11416
parent de3a68a1
...@@ -939,6 +939,10 @@ init_cumulative_args (cum, fntype, libname, incoming) ...@@ -939,6 +939,10 @@ init_cumulative_args (cum, fntype, libname, incoming)
&& lookup_attribute ("dllimport", TYPE_ATTRIBUTES (fntype))) && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (fntype)))
cum->call_cookie = CALL_NT_DLLIMPORT; cum->call_cookie = CALL_NT_DLLIMPORT;
/* Also check for longcall's */
else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
cum->call_cookie = CALL_LONG;
if (TARGET_DEBUG_ARG) if (TARGET_DEBUG_ARG)
{ {
fprintf (stderr, "\ninit_cumulative_args:"); fprintf (stderr, "\ninit_cumulative_args:");
...@@ -952,9 +956,12 @@ init_cumulative_args (cum, fntype, libname, incoming) ...@@ -952,9 +956,12 @@ init_cumulative_args (cum, fntype, libname, incoming)
if (abi == ABI_V4 && incoming) if (abi == ABI_V4 && incoming)
fprintf (stderr, " varargs = %d, ", cum->varargs_offset); fprintf (stderr, " varargs = %d, ", cum->varargs_offset);
if (cum->call_cookie == CALL_NT_DLLIMPORT) if (cum->call_cookie & CALL_NT_DLLIMPORT)
fprintf (stderr, " dllimport,"); fprintf (stderr, " dllimport,");
if (cum->call_cookie & CALL_LONG)
fprintf (stderr, " longcall,");
fprintf (stderr, " proto = %d, nargs = %d\n", fprintf (stderr, " proto = %d, nargs = %d\n",
cum->prototype, cum->nargs_prototype); cum->prototype, cum->nargs_prototype);
} }
...@@ -1089,12 +1096,10 @@ function_arg (cum, mode, type, named) ...@@ -1089,12 +1096,10 @@ function_arg (cum, mode, type, named)
&& cum->nargs_prototype < 0 && cum->nargs_prototype < 0
&& type && (cum->prototype || TARGET_NO_PROTOTYPE)) && type && (cum->prototype || TARGET_NO_PROTOTYPE))
{ {
if (cum->call_cookie != CALL_NORMAL) return GEN_INT (cum->call_cookie
abort (); | ((cum->fregno == FP_ARG_MIN_REG)
? CALL_V4_SET_FP_ARGS
return GEN_INT ((cum->fregno == FP_ARG_MIN_REG) : CALL_V4_CLEAR_FP_ARGS));
? CALL_V4_SET_FP_ARGS
: CALL_V4_CLEAR_FP_ARGS);
} }
return GEN_INT (cum->call_cookie); return GEN_INT (cum->call_cookie);
...@@ -4248,6 +4253,11 @@ rs6000_valid_type_attribute_p (type, attributes, identifier, args) ...@@ -4248,6 +4253,11 @@ rs6000_valid_type_attribute_p (type, attributes, identifier, args)
&& TREE_CODE (type) != TYPE_DECL) && TREE_CODE (type) != TYPE_DECL)
return 0; return 0;
/* Longcall attribute says that the function is not within 2**26 bytes
of the current function, and to do an indirect call. */
if (is_attribute_p ("longcall", identifier))
return (args == NULL_TREE);
if (DEFAULT_ABI == ABI_NT) if (DEFAULT_ABI == ABI_NT)
{ {
/* Stdcall attribute says callee is responsible for popping arguments /* Stdcall attribute says callee is responsible for popping arguments
...@@ -4324,6 +4334,34 @@ rs6000_dll_import_ref (call_ref) ...@@ -4324,6 +4334,34 @@ rs6000_dll_import_ref (call_ref)
return reg2; return reg2;
} }
/* Return a reference suitable for calling a function with the longcall attribute. */
struct rtx_def *
rs6000_longcall_ref (call_ref)
rtx call_ref;
{
char *call_name;
int len;
char *p;
rtx reg1, reg2;
tree node;
if (GET_CODE (call_ref) != SYMBOL_REF)
return call_ref;
/* System V adds '.' to the internal name, so skip them. */
call_name = XSTR (call_ref, 0);
if (*call_name == '.')
{
while (*call_name == '.')
call_name++;
node = get_identifier (call_name);
call_ref = gen_rtx (SYMBOL_REF, VOIDmode, IDENTIFIER_POINTER (node));
}
return force_reg (Pmode, call_ref);
}
/* A C statement or statements to switch to the appropriate section /* A C statement or statements to switch to the appropriate section
for output of RTX in mode MODE. You can assume that RTX is some for output of RTX in mode MODE. You can assume that RTX is some
......
...@@ -1246,13 +1246,11 @@ extern int rs6000_sysv_varargs_p; ...@@ -1246,13 +1246,11 @@ extern int rs6000_sysv_varargs_p;
#define FP_ARG_RETURN FP_ARG_MIN_REG #define FP_ARG_RETURN FP_ARG_MIN_REG
/* Flags for the call/call_value rtl operations set up by function_arg */ /* Flags for the call/call_value rtl operations set up by function_arg */
enum rs6000_call_cookie #define CALL_NORMAL 0x00000000 /* no special processing */
{ #define CALL_NT_DLLIMPORT 0x00000001 /* NT, this is a DLL import call */
CALL_V4_SET_FP_ARGS = -1, /* V4, FP args passed */ #define CALL_V4_CLEAR_FP_ARGS 0x00000002 /* V.4, no FP args passed */
CALL_NORMAL = 0, /* no special processing */ #define CALL_V4_SET_FP_ARGS 0x00000004 /* V.4, FP args were passed */
CALL_V4_CLEAR_FP_ARGS = 1, /* V4, no FP args passed */ #define CALL_LONG 0x00000008 /* always call indirect */
CALL_NT_DLLIMPORT = 2 /* NT, this is a DLL import call */
};
/* Define cutoff for using external functions to save floating point */ /* Define cutoff for using external functions to save floating point */
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63) #define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
...@@ -1287,13 +1285,13 @@ enum rs6000_call_cookie ...@@ -1287,13 +1285,13 @@ enum rs6000_call_cookie
typedef struct rs6000_args typedef struct rs6000_args
{ {
int words; /* # words uses for passing GP registers */ int words; /* # words uses for passing GP registers */
int fregno; /* next available FP register */ int fregno; /* next available FP register */
int nargs_prototype; /* # args left in the current prototype */ int nargs_prototype; /* # args left in the current prototype */
int orig_nargs; /* Original value of nargs_prototype */ int orig_nargs; /* Original value of nargs_prototype */
int varargs_offset; /* offset of the varargs save area */ int varargs_offset; /* offset of the varargs save area */
int prototype; /* Whether a prototype was defined */ int prototype; /* Whether a prototype was defined */
enum rs6000_call_cookie call_cookie; /* Do special things for this call */ int call_cookie; /* Do special things for this call */
} CUMULATIVE_ARGS; } CUMULATIVE_ARGS;
/* Define intermediate macro to compute the size (in registers) of an argument /* Define intermediate macro to compute the size (in registers) of an argument
...@@ -2879,3 +2877,4 @@ extern int rs6000_valid_decl_attribute_p (); ...@@ -2879,3 +2877,4 @@ extern int rs6000_valid_decl_attribute_p ();
extern int rs6000_valid_type_attribute_p (); extern int rs6000_valid_type_attribute_p ();
extern void rs6000_set_default_type_attributes (); extern void rs6000_set_default_type_attributes ();
extern struct rtx_def *rs6000_dll_import_ref (); extern struct rtx_def *rs6000_dll_import_ref ();
extern struct rtx_def *rs6000_longcall_ref ();
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