diff options
author | Michael Meissner <meissner@gcc.gnu.org> | 1996-03-04 16:34:29 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 1996-03-04 16:34:29 +0000 |
commit | 6a4cee5fdb4e3367b77d3bbe700a7e132616037c (patch) | |
tree | b2cea70495238983f6ab5e53aee0d4c5f53d77d8 /gcc | |
parent | de3a68a106506d13e4429f868c3af140a022c6a3 (diff) | |
download | gcc-6a4cee5fdb4e3367b77d3bbe700a7e132616037c.zip gcc-6a4cee5fdb4e3367b77d3bbe700a7e132616037c.tar.gz gcc-6a4cee5fdb4e3367b77d3bbe700a7e132616037c.tar.bz2 |
Add attribute((longcall)) support
From-SVN: r11416
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 52 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 27 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 130 |
3 files changed, 131 insertions, 78 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 54f552a..401faa6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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) - ? CALL_V4_SET_FP_ARGS - : CALL_V4_CLEAR_FP_ARGS); + return GEN_INT (cum->call_cookie + | ((cum->fregno == FP_ARG_MIN_REG) + ? CALL_V4_SET_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 diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 461079a..d2e34a6 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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) @@ -1287,13 +1285,13 @@ enum rs6000_call_cookie typedef struct rs6000_args { - int words; /* # words uses for passing GP registers */ - int fregno; /* next available FP register */ - int nargs_prototype; /* # args left in the current prototype */ - 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 words; /* # words uses for passing GP registers */ + int fregno; /* next available FP register */ + int nargs_prototype; /* # args left in the current prototype */ + int orig_nargs; /* Original value of nargs_prototype */ + int varargs_offset; /* offset of the varargs save area */ + int prototype; /* Whether a prototype was defined */ + 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 (); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 76f6c2e..24b6cb0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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\"; }" |