Commit efdba735 by Stuart Hastings Committed by Stuart Hastings

2003-12-04 Stuart Hastings <stuart@apple.com>

        * rs6000.c (output_call, macho_branch_islands,
        add_compiler_branch_island, no_previous_def, get_previous_label)
        Revisions of xx_stub functions for branch islands,
        add -fPIC support for Darwin.
        * rs6000-protos.h (output_call) Prototype.
        * rs6000.md Use output_call.
        * invoke.texi Explain Darwin semantics of -longcall.
        * testsuite/gcc.dg/darwin-abi-1.c Revise testcase for -longcall/jbsr.

From-SVN: r74302
parent 22c3768c
2003-12-04 Stuart Hastings <stuart@apple.com>
* rs6000.c (output_call, macho_branch_islands,
add_compiler_branch_island, no_previous_def, get_previous_label)
Revisions of xx_stub functions for branch islands,
add -fPIC support for Darwin.
* rs6000-protos.h (output_call) Prototype.
* rs6000.md Use output_call.
* invoke.texi Explain Darwin semantics of -longcall.
* testsuite/gcc.dg/darwin-abi-1.c Revise testcase for -longcall/jbsr.
2003-12-04 Richard Henderson <rth@redhat.com> 2003-12-04 Richard Henderson <rth@redhat.com>
* config/i386/i386.md (addqi3_carry): Use q not r constraints. * config/i386/i386.md (addqi3_carry): Use q not r constraints.
......
...@@ -201,4 +201,8 @@ extern int rs6000_tls_symbol_ref (rtx, enum machine_mode); ...@@ -201,4 +201,8 @@ extern int rs6000_tls_symbol_ref (rtx, enum machine_mode);
extern void rs6000_pragma_longcall (struct cpp_reader *); extern void rs6000_pragma_longcall (struct cpp_reader *);
extern void rs6000_cpu_cpp_builtins (struct cpp_reader *); extern void rs6000_cpu_cpp_builtins (struct cpp_reader *);
#if TARGET_MACHO
char *output_call (rtx, rtx *, int, int);
#endif
#endif /* rs6000-protos.h */ #endif /* rs6000-protos.h */
...@@ -399,6 +399,13 @@ static void rs6000_move_block_from_reg(int regno, rtx x, int nregs); ...@@ -399,6 +399,13 @@ static void rs6000_move_block_from_reg(int regno, rtx x, int nregs);
static void setup_incoming_varargs (CUMULATIVE_ARGS *, static void setup_incoming_varargs (CUMULATIVE_ARGS *,
enum machine_mode, tree, enum machine_mode, tree,
int *, int); int *, int);
#if TARGET_MACHO
static void macho_branch_islands (void);
static void add_compiler_branch_island (tree, tree, int);
static int no_previous_def (tree function_name);
static tree get_prev_label (tree function_name);
#endif
static tree rs6000_build_builtin_va_list (void); static tree rs6000_build_builtin_va_list (void);
/* Hash table stuff for keeping track of TOC entries. */ /* Hash table stuff for keeping track of TOC entries. */
...@@ -12432,7 +12439,8 @@ rs6000_output_function_epilogue (FILE *file, ...@@ -12432,7 +12439,8 @@ rs6000_output_function_epilogue (FILE *file,
} }
} }
#if TARGET_OBJECT_FORMAT == OBJECT_MACHO #if TARGET_MACHO
macho_branch_islands ();
/* Mach-O doesn't support labels at the end of objects, so if /* Mach-O doesn't support labels at the end of objects, so if
it looks like we might want one, insert a NOP. */ it looks like we might want one, insert a NOP. */
{ {
...@@ -14719,83 +14727,118 @@ symbolic_operand (rtx op) ...@@ -14719,83 +14727,118 @@ symbolic_operand (rtx op)
} }
#endif #endif
#ifdef RS6000_LONG_BRANCH #if TARGET_MACHO
static tree stub_list = 0; static tree branch_island_list = 0;
/* ADD_COMPILER_STUB adds the compiler generated stub for handling /* Remember to generate a branch island for far calls to the given
procedure calls to the linked list. */ function. */
void static void
add_compiler_stub (tree label_name, tree function_name, int line_number) add_compiler_branch_island (tree label_name, tree function_name, int line_number)
{ {
tree stub = build_tree_list (function_name, label_name); tree branch_island = build_tree_list (function_name, label_name);
TREE_TYPE (stub) = build_int_2 (line_number, 0); TREE_TYPE (branch_island) = build_int_2 (line_number, 0);
TREE_CHAIN (stub) = stub_list; TREE_CHAIN (branch_island) = branch_island_list;
stub_list = stub; branch_island_list = branch_island;
} }
#define STUB_LABEL_NAME(STUB) TREE_VALUE (STUB) #define BRANCH_ISLAND_LABEL_NAME(BRANCH_ISLAND) TREE_VALUE (BRANCH_ISLAND)
#define STUB_FUNCTION_NAME(STUB) TREE_PURPOSE (STUB) #define BRANCH_ISLAND_FUNCTION_NAME(BRANCH_ISLAND) TREE_PURPOSE (BRANCH_ISLAND)
#define STUB_LINE_NUMBER(STUB) TREE_INT_CST_LOW (TREE_TYPE (STUB)) #define BRANCH_ISLAND_LINE_NUMBER(BRANCH_ISLAND) \
TREE_INT_CST_LOW (TREE_TYPE (BRANCH_ISLAND))
/* OUTPUT_COMPILER_STUB outputs the compiler generated stub for /* Generate far-jump branch islands for everything on the
handling procedure calls from the linked list and initializes the branch_island_list. Invoked immediately after the last instruction
linked list. */ of the epilogue has been emitted; the branch-islands must be
appended to, and contiguous with, the function body. Mach-O stubs
are generated in machopic_output_stub(). */
void static void
output_compiler_stub (void) macho_branch_islands (void)
{ {
char tmp_buf[256]; char tmp_buf[512];
char label_buf[256]; tree branch_island;
tree stub;
if (!flag_pic) for (branch_island = branch_island_list;
for (stub = stub_list; stub; stub = TREE_CHAIN (stub)) branch_island;
branch_island = TREE_CHAIN (branch_island))
{ {
fprintf (asm_out_file, const char *label =
"%s:\n", IDENTIFIER_POINTER(STUB_LABEL_NAME(stub))); IDENTIFIER_POINTER (BRANCH_ISLAND_LABEL_NAME (branch_island));
const char *name =
darwin_strip_name_encoding (
IDENTIFIER_POINTER (BRANCH_ISLAND_FUNCTION_NAME (branch_island)));
char name_buf[512];
/* Cheap copy of the details from the Darwin ASM_OUTPUT_LABELREF(). */
if (name[0] == '*' || name[0] == '&')
strcpy (name_buf, name+1);
else
{
name_buf[0] = '_';
strcpy (name_buf+1, name);
}
strcpy (tmp_buf, "\n");
strcat (tmp_buf, label);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
fprintf (asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER(stub)); fprintf (asm_out_file, "\t.stabd 68,0,%lu\n",
BRANCH_ISLAND_LINE_NUMBER(branch_island));
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
if (flag_pic)
{
strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic\n");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic:\n\tmflr r11\n");
strcat (tmp_buf, "\taddis r11,r11,ha16(");
strcat (tmp_buf, name_buf);
strcat (tmp_buf, " - ");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic)\n");
if (IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))[0] == '*') strcat (tmp_buf, "\tmtlr r0\n");
strcpy (label_buf,
IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))+1); strcat (tmp_buf, "\taddi r12,r11,lo16(");
strcat (tmp_buf, name_buf);
strcat (tmp_buf, " - ");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic)\n");
strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
}
else else
{ {
label_buf[0] = '_'; strcat (tmp_buf, ":\nlis r12,hi16(");
strcpy (label_buf+1, strcat (tmp_buf, name_buf);
IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub)));
}
strcpy (tmp_buf, "lis r12,hi16(");
strcat (tmp_buf, label_buf);
strcat (tmp_buf, ")\n\tori r12,r12,lo16("); strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
strcat (tmp_buf, label_buf); strcat (tmp_buf, name_buf);
strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr"); strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
}
output_asm_insn (tmp_buf, 0); output_asm_insn (tmp_buf, 0);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
fprintf(asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER (stub)); fprintf(asm_out_file, "\t.stabd 68,0,%lu\n",
BRANCH_ISLAND_LINE_NUMBER (branch_island));
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */ #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
} }
stub_list = 0; branch_island_list = 0;
} }
/* NO_PREVIOUS_DEF checks in the link list whether the function name is /* NO_PREVIOUS_DEF checks in the link list whether the function name is
already there or not. */ already there or not. */
int static int
no_previous_def (tree function_name) no_previous_def (tree function_name)
{ {
tree stub; tree branch_island;
for (stub = stub_list; stub; stub = TREE_CHAIN (stub)) for (branch_island = branch_island_list;
if (function_name == STUB_FUNCTION_NAME (stub)) branch_island;
branch_island = TREE_CHAIN (branch_island))
if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
return 0; return 0;
return 1; return 1;
} }
...@@ -14803,13 +14846,15 @@ no_previous_def (tree function_name) ...@@ -14803,13 +14846,15 @@ no_previous_def (tree function_name)
/* GET_PREV_LABEL gets the label name from the previous definition of /* GET_PREV_LABEL gets the label name from the previous definition of
the function. */ the function. */
tree static tree
get_prev_label (tree function_name) get_prev_label (tree function_name)
{ {
tree stub; tree branch_island;
for (stub = stub_list; stub; stub = TREE_CHAIN (stub)) for (branch_island = branch_island_list;
if (function_name == STUB_FUNCTION_NAME (stub)) branch_island;
return STUB_LABEL_NAME (stub); branch_island = TREE_CHAIN (branch_island))
if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
return BRANCH_ISLAND_LABEL_NAME (branch_island);
return 0; return 0;
} }
...@@ -14819,13 +14864,14 @@ get_prev_label (tree function_name) ...@@ -14819,13 +14864,14 @@ get_prev_label (tree function_name)
CALL_DEST is the routine we are calling. */ CALL_DEST is the routine we are calling. */
char * char *
output_call (rtx insn, rtx call_dest, int operand_number) output_call (rtx insn, rtx *operands, int dest_operand_number, int cookie_operand_number)
{ {
static char buf[256]; static char buf[256];
if (GET_CODE (call_dest) == SYMBOL_REF && TARGET_LONG_BRANCH && !flag_pic) if (GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
&& (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
{ {
tree labelname; tree labelname;
tree funname = get_identifier (XSTR (call_dest, 0)); tree funname = get_identifier (XSTR (operands[dest_operand_number], 0));
if (no_previous_def (funname)) if (no_previous_def (funname))
{ {
...@@ -14839,23 +14885,25 @@ output_call (rtx insn, rtx call_dest, int operand_number) ...@@ -14839,23 +14885,25 @@ output_call (rtx insn, rtx call_dest, int operand_number)
for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn)); for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
if (insn) if (insn)
line_number = NOTE_LINE_NUMBER (insn); line_number = NOTE_LINE_NUMBER (insn);
add_compiler_stub (labelname, funname, line_number); add_compiler_branch_island (labelname, funname, line_number);
} }
else else
labelname = get_prev_label (funname); labelname = get_prev_label (funname);
/* "jbsr foo, L42" is Mach-O for "Link as 'bl foo' if a 'bl'
instruction will reach 'foo', otherwise link as 'bl L42'".
"L42" should be a 'branch island', that will do a far jump to
'foo'. Branch islands are generated in
macho_branch_islands(). */
sprintf (buf, "jbsr %%z%d,%.246s", sprintf (buf, "jbsr %%z%d,%.246s",
operand_number, IDENTIFIER_POINTER (labelname)); dest_operand_number, IDENTIFIER_POINTER (labelname));
return buf;
} }
else else
{ sprintf (buf, "bl %%z%d", dest_operand_number);
sprintf (buf, "bl %%z%d", operand_number);
return buf; return buf;
}
} }
#endif /* RS6000_LONG_BRANCH */ #endif /* TARGET_MACHO */
/* Generate PIC and indirect symbol stubs. */ /* Generate PIC and indirect symbol stubs. */
......
...@@ -10273,7 +10273,7 @@ ...@@ -10273,7 +10273,7 @@
if (GET_CODE (operands[0]) != SYMBOL_REF if (GET_CODE (operands[0]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0])) || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|| (INTVAL (operands[2]) & CALL_LONG) != 0) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
{ {
if (INTVAL (operands[2]) & CALL_LONG) if (INTVAL (operands[2]) & CALL_LONG)
operands[0] = rs6000_longcall_ref (operands[0]); operands[0] = rs6000_longcall_ref (operands[0]);
...@@ -10321,7 +10321,7 @@ ...@@ -10321,7 +10321,7 @@
if (GET_CODE (operands[1]) != SYMBOL_REF if (GET_CODE (operands[1]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1])) || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|| (INTVAL (operands[3]) & CALL_LONG) != 0) || (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
{ {
if (INTVAL (operands[3]) & CALL_LONG) if (INTVAL (operands[3]) & CALL_LONG)
operands[1] = rs6000_longcall_ref (operands[1]); operands[1] = rs6000_longcall_ref (operands[1]);
...@@ -10576,9 +10576,9 @@ ...@@ -10576,9 +10576,9 @@
(match_operand 1 "" "g,g")) (match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n")) (use (match_operand:SI 2 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 3 "=l,l"))] (clobber (match_scratch:SI 3 "=l,l"))]
"(DEFAULT_ABI == ABI_V4 "(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_DARWIN) || (DEFAULT_ABI == ABI_V4
&& (INTVAL (operands[2]) & CALL_LONG) == 0" && (INTVAL (operands[2]) & CALL_LONG) == 0))"
{ {
if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS)
output_asm_insn ("crxor 6,6,6", operands); output_asm_insn ("crxor 6,6,6", operands);
...@@ -10586,7 +10586,11 @@ ...@@ -10586,7 +10586,11 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn ("creqv 6,6,6", operands); output_asm_insn ("creqv 6,6,6", operands);
#ifdef TARGET_MACHO
return output_call(insn, operands, 0, 2);
#else
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0"; return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
#endif
} }
[(set_attr "type" "branch,branch") [(set_attr "type" "branch,branch")
(set_attr "length" "4,8")]) (set_attr "length" "4,8")])
...@@ -10617,9 +10621,9 @@ ...@@ -10617,9 +10621,9 @@
(match_operand 2 "" "g,g"))) (match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n")) (use (match_operand:SI 3 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 4 "=l,l"))] (clobber (match_scratch:SI 4 "=l,l"))]
"(DEFAULT_ABI == ABI_V4 "(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_DARWIN) || (DEFAULT_ABI == ABI_V4
&& (INTVAL (operands[3]) & CALL_LONG) == 0" && (INTVAL (operands[3]) & CALL_LONG) == 0))"
{ {
if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS)
output_asm_insn ("crxor 6,6,6", operands); output_asm_insn ("crxor 6,6,6", operands);
...@@ -10627,7 +10631,11 @@ ...@@ -10627,7 +10631,11 @@
else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn ("creqv 6,6,6", operands); output_asm_insn ("creqv 6,6,6", operands);
#ifdef TARGET_MACHO
return output_call(insn, operands, 1, 3);
#else
return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1"; return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
#endif
} }
[(set_attr "type" "branch,branch") [(set_attr "type" "branch,branch")
(set_attr "length" "4,8")]) (set_attr "length" "4,8")])
......
...@@ -7784,6 +7784,10 @@ generate slower code. As of this writing, the AIX linker can do this, ...@@ -7784,6 +7784,10 @@ generate slower code. As of this writing, the AIX linker can do this,
as can the GNU linker for PowerPC/64. It is planned to add this feature as can the GNU linker for PowerPC/64. It is planned to add this feature
to the GNU linker for 32-bit PowerPC systems as well. to the GNU linker for 32-bit PowerPC systems as well.
On Mach-O (Darwin) systems, this option directs the compiler emit to
the glue for every direct call, and the Darwin linker decides whether
to use or discard it.
In the future, we may cause GCC to ignore all longcall specifications In the future, we may cause GCC to ignore all longcall specifications
when the linker is known to generate glue. when the linker is known to generate glue.
......
/* { dg-do compile { target powerpc*-*-darwin* } } */ /* { dg-do compile { target powerpc*-*-darwin* } } */
/* { dg-options "-O" } */ /* { dg-options "-O" } */
/* { dg-final { scan-assembler "li r3,12345\n\tbl " } } */ /* { dg-final { scan-assembler "li r3,12345\n\t(bl|jbsr) " } } */
/* Check that zero-size structures don't affect parameter passing. */ /* Check that zero-size structures don't affect parameter passing. */
......
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