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)
&& lookup_attribute ("dllimport", TYPE_ATTRIBUTES (fntype)))
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)
{
fprintf (stderr, "\ninit_cumulative_args:");
......@@ -952,9 +956,12 @@ init_cumulative_args (cum, fntype, libname, incoming)
if (abi == ABI_V4 && incoming)
fprintf (stderr, " varargs = %d, ", cum->varargs_offset);
if (cum->call_cookie == CALL_NT_DLLIMPORT)
if (cum->call_cookie & CALL_NT_DLLIMPORT)
fprintf (stderr, " dllimport,");
if (cum->call_cookie & CALL_LONG)
fprintf (stderr, " longcall,");
fprintf (stderr, " proto = %d, nargs = %d\n",
cum->prototype, cum->nargs_prototype);
}
......@@ -1089,12 +1096,10 @@ function_arg (cum, mode, type, named)
&& cum->nargs_prototype < 0
&& type && (cum->prototype || TARGET_NO_PROTOTYPE))
{
if (cum->call_cookie != CALL_NORMAL)
abort ();
return GEN_INT ((cum->fregno == FP_ARG_MIN_REG)
return GEN_INT (cum->call_cookie
| ((cum->fregno == FP_ARG_MIN_REG)
? CALL_V4_SET_FP_ARGS
: CALL_V4_CLEAR_FP_ARGS);
: CALL_V4_CLEAR_FP_ARGS));
}
return GEN_INT (cum->call_cookie);
......@@ -4248,6 +4253,11 @@ rs6000_valid_type_attribute_p (type, attributes, identifier, args)
&& TREE_CODE (type) != TYPE_DECL)
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)
{
/* Stdcall attribute says callee is responsible for popping arguments
......@@ -4324,6 +4334,34 @@ rs6000_dll_import_ref (call_ref)
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
for output of RTX in mode MODE. You can assume that RTX is some
......
......@@ -1246,13 +1246,11 @@ extern int rs6000_sysv_varargs_p;
#define FP_ARG_RETURN FP_ARG_MIN_REG
/* Flags for the call/call_value rtl operations set up by function_arg */
enum rs6000_call_cookie
{
CALL_V4_SET_FP_ARGS = -1, /* V4, FP args passed */
CALL_NORMAL = 0, /* no special processing */
CALL_V4_CLEAR_FP_ARGS = 1, /* V4, no FP args passed */
CALL_NT_DLLIMPORT = 2 /* NT, this is a DLL import call */
};
#define CALL_NORMAL 0x00000000 /* no special processing */
#define CALL_NT_DLLIMPORT 0x00000001 /* NT, this is a DLL import call */
#define CALL_V4_CLEAR_FP_ARGS 0x00000002 /* V.4, no FP args passed */
#define CALL_V4_SET_FP_ARGS 0x00000004 /* V.4, FP args were passed */
#define CALL_LONG 0x00000008 /* always call indirect */
/* Define cutoff for using external functions to save floating point */
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
......@@ -1293,7 +1291,7 @@ typedef struct rs6000_args
int orig_nargs; /* Original value of nargs_prototype */
int varargs_offset; /* offset of the varargs save area */
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;
/* Define intermediate macro to compute the size (in registers) of an argument
......@@ -2879,3 +2877,4 @@ extern int rs6000_valid_decl_attribute_p ();
extern int rs6000_valid_type_attribute_p ();
extern void rs6000_set_default_type_attributes ();
extern struct rtx_def *rs6000_dll_import_ref ();
extern struct rtx_def *rs6000_longcall_ref ();
......@@ -6541,27 +6541,29 @@
(define_insn "call_indirect_aix"
[(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
(match_operand 1 "const_int_operand" "n"))
(use (match_operand 2 "const_int_operand" "O"))
(use (match_operand 2 "const_int_operand" "n"))
(use (match_operand 3 "offsettable_addr_operand" "p"))
(use (match_operand 4 "register_operand" "r"))
(clobber (match_operand 5 "register_operand" "=r"))
(clobber (match_scratch:SI 6 "=&r"))
(clobber (match_scratch:SI 7 "=l"))]
"DEFAULT_ABI == ABI_AIX"
"{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0);\;mt%7 %6\;{l|lwz} %5,8(%0)\;{brl|blrl}\;{l|lwz} %4,%a3"
"DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) == CALL_NORMAL || (INTVAL (operands[2]) & CALL_LONG) != 0)"
"{st|stw} %4,%a3\;{l|lwz} %6,0(%0)\;{l|lwz} %4,4(%0)\;mt%7 %6\;{l|lwz} %5,8(%0)\;{brl|blrl}\;{l|lwz} %4,%a3"
[(set_attr "length" "28")])
(define_insn "call_value_indirect_aix"
[(set (match_operand 0 "register_operand" "fg")
(call (mem:SI (match_operand:SI 1 "register_operand" "b"))
(match_operand 2 "const_int_operand" "n")))
(use (match_operand 3 "const_int_operand" "O"))
(use (match_operand 3 "const_int_operand" "n"))
(use (match_operand 4 "offsettable_addr_operand" "p"))
(use (match_operand 5 "register_operand" "r"))
(clobber (match_operand 6 "register_operand" "=r"))
(clobber (match_scratch:SI 7 "=&r"))
(clobber (match_scratch:SI 8 "=l"))]
"DEFAULT_ABI == ABI_AIX"
"DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
"{st|stw} %5,%a4\;{l|lwz} %7,0(%1)\;{l|lwz} %5,4(%1);\;mt%8 %7\;{l|lwz} %6,8(%1)\;{brl|blrl}\;{l|lwz} %5,%a4"
[(set_attr "length" "28")])
......@@ -6582,12 +6584,13 @@
(define_insn "call_indirect_nt"
[(call (mem:SI (match_operand:SI 0 "register_operand" "b"))
(match_operand 1 "const_int_operand" "n"))
(use (match_operand 2 "const_int_operand" "O"))
(use (match_operand 2 "const_int_operand" "n"))
(use (match_operand 3 "offsettable_addr_operand" "p"))
(use (match_operand 4 "register_operand" "r"))
(clobber (match_scratch:SI 5 "=&r"))
(clobber (match_scratch:SI 6 "=l"))]
"DEFAULT_ABI == ABI_NT"
"DEFAULT_ABI == ABI_NT
&& (INTVAL (operands[2]) == CALL_NORMAL || (INTVAL (operands[2]) & CALL_LONG) != 0)"
"{st|stw} %4,%a3\;{l|lwz} %5,0(%0)\;{l|lwz} %4,4(%0)\;mt%6 %5\;{brl|blrl}\;{l|lwz} %4,%a3"
[(set_attr "length" "24")])
......@@ -6595,12 +6598,13 @@
[(set (match_operand 0 "register_operand" "fg")
(call (mem:SI (match_operand:SI 1 "register_operand" "b"))
(match_operand 2 "const_int_operand" "n")))
(use (match_operand 3 "const_int_operand" "O"))
(use (match_operand 3 "const_int_operand" "n"))
(use (match_operand 4 "offsettable_addr_operand" "p"))
(use (match_operand 5 "register_operand" "r"))
(clobber (match_scratch:SI 6 "=&r"))
(clobber (match_scratch:SI 7 "=l"))]
"DEFAULT_ABI == ABI_NT"
"DEFAULT_ABI == ABI_NT
&& (INTVAL (operands[3]) == CALL_NORMAL || (INTVAL (operands[3]) & CALL_LONG) != 0)"
"{st|stw} %5,%a4\;{l|lwz} %6,0(%1)\;{l|lwz} %5,4(%1)\;mt%7 %6\;{brl|blrl}\;{l|lwz} %5,%a4"
[(set_attr "length" "24")])
......@@ -6617,11 +6621,11 @@
"DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC"
"*
{
if (INTVAL (operands[2]) > 0)
return \"creqv 6,6,6\;{brl|blrl}\";
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) < 0)
return \"crxor 6,6,6\;{brl|blrl}\";
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"{brl|blrl}\";
}"
......@@ -6636,11 +6640,11 @@
"DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC"
"*
{
if (INTVAL (operands[3]) > 0)
return \"creqv 6,6,6\;{brl|blrl}\";
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) < 0)
return \"crxor 6,6,6\;{brl|blrl}\";
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"{brl|blrl}\";
}"
......@@ -6662,14 +6666,18 @@
/* Convert NT DLL imports into an indirect call. */
if (GET_CODE (operands[0]) == SYMBOL_REF
&& INTVAL (operands[2]) == (int)CALL_NT_DLLIMPORT)
&& (INTVAL (operands[2]) & CALL_NT_DLLIMPORT) != 0)
{
operands[0] = rs6000_dll_import_ref (operands[0]);
operands[2] = GEN_INT ((int)CALL_NORMAL);
}
if (GET_CODE (operands[0]) != SYMBOL_REF)
if (GET_CODE (operands[0]) != SYMBOL_REF
|| (INTVAL (operands[2]) & CALL_LONG) != 0)
{
if (INTVAL (operands[2]) & CALL_LONG)
operands[0] = rs6000_longcall_ref (operands[0]);
if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
emit_call_insn (gen_call_indirect_sysv (force_reg (Pmode, operands[0]),
operands[1], operands[2]));
......@@ -6717,14 +6725,18 @@
/* Convert NT DLL imports into an indirect call. */
if (GET_CODE (operands[1]) == SYMBOL_REF
&& INTVAL (operands[3]) == (int)CALL_NT_DLLIMPORT)
&& (INTVAL (operands[3]) & CALL_NT_DLLIMPORT) != 0)
{
operands[1] = rs6000_dll_import_ref (operands[1]);
operands[3] = GEN_INT ((int)CALL_NORMAL);
}
if (GET_CODE (operands[1]) != SYMBOL_REF)
if (GET_CODE (operands[1]) != SYMBOL_REF
|| (INTVAL (operands[3]) & CALL_LONG) != 0)
{
if (INTVAL (operands[2]) & CALL_LONG)
operands[1] = rs6000_longcall_ref (operands[1]);
if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_AIX_NODESC)
emit_call_insn (gen_call_value_indirect_sysv (operands[0], operands[1],
operands[2], operands[3]));
......@@ -6769,14 +6781,14 @@
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 3 "=l,l"))]
""
"INTVAL (operands[2]) != CALL_LONG"
"*
{
switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"bl %z0\";
}"
......@@ -6794,18 +6806,19 @@
(match_operand 1 "" "fg,fg"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 3 "=l,l"))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
&& INTVAL (operands[2]) != CALL_LONG"
"*
{
/* Indirect calls should go through call_indirect */
if (GET_CODE (operands[0]) == REG)
abort ();
switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (TARGET_WINDOWS_NT) ? \"bl %z0\;.znop %z0\" : \"bl %z0\;%.\";
}"
......@@ -6816,18 +6829,19 @@
(match_operand 1 "" "fg,fg"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 3 "=l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
"(DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4)
&& INTVAL (operands[2]) != CALL_LONG"
"*
{
/* Indirect calls should go through call_indirect */
if (GET_CODE (operands[0]) == REG)
abort ();
switch ((enum rs6000_call_cookie)INTVAL (operands[2]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"bl %z0\";
}"
......@@ -6839,14 +6853,14 @@
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 4 "=l,l"))]
""
"INTVAL (operands[3]) != CALL_LONG"
"*
{
switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"bl %z1\";
}"
......@@ -6858,18 +6872,19 @@
(match_operand 2 "" "fg,fg")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 4 "=l,l"))]
"DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT"
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)
&& INTVAL (operands[3]) != CALL_LONG"
"*
{
/* This should be handled by call_value_indirect */
if (GET_CODE (operands[1]) == REG)
abort ();
switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return (TARGET_WINDOWS_NT) ? \"bl %z1\;.znop %z1\" : \"bl %z1\;%.\";
}"
......@@ -6881,18 +6896,19 @@
(match_operand 2 "" "fg,fg")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 4 "=l,l"))]
"DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4"
"(DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4)
&& INTVAL (operands[3]) != CALL_LONG"
"*
{
/* This should be handled by call_value_indirect */
if (GET_CODE (operands[1]) == REG)
abort ();
switch ((enum rs6000_call_cookie)INTVAL (operands[3]))
{
case CALL_V4_SET_FP_ARGS: output_asm_insn (\"crxor 6,6,6\", operands); break;
case CALL_V4_CLEAR_FP_ARGS: output_asm_insn (\"creqv 6,6,6\", operands); break;
}
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn (\"crxor 6,6,6\", operands);
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
return \"bl %z1\";
}"
......
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