OSDN Git Service

2003-12-04 Stuart Hastings <stuart@apple.com>
authorstuart <stuart@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Dec 2003 00:44:57 +0000 (00:44 +0000)
committerstuart <stuart@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Dec 2003 00:44:57 +0000 (00:44 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74302 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/doc/invoke.texi
gcc/testsuite/gcc.dg/darwin-abi-1.c

index f85c136..428e954 100644 (file)
@@ -1,3 +1,14 @@
+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>
 
        * config/i386/i386.md (addqi3_carry): Use q not r constraints.
index ed13c34..57fca19 100644 (file)
@@ -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_cpu_cpp_builtins (struct cpp_reader *);
 
+#if TARGET_MACHO
+char *output_call (rtx, rtx *, int, int);
+#endif
+
 #endif  /* rs6000-protos.h */
index 8a7e0e6..cc62bc5 100644 (file)
@@ -399,6 +399,13 @@ static void rs6000_move_block_from_reg(int regno, rtx x, int nregs);
 static void setup_incoming_varargs (CUMULATIVE_ARGS *,
                                    enum machine_mode, tree,
                                    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);
 
 /* Hash table stuff for keeping track of TOC entries.  */
@@ -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
      it looks like we might want one, insert a NOP.  */
   {
@@ -14719,83 +14727,118 @@ symbolic_operand (rtx op)
 }
 #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 
-   procedure calls to the linked list.  */
+/* Remember to generate a branch island for far calls to the given
+   function.  */
 
-void 
-add_compiler_stub (tree label_name, tree function_name, int line_number)
+static void 
+add_compiler_branch_island (tree label_name, tree function_name, int line_number)
 {
-  tree stub = build_tree_list (function_name, label_name);
-  TREE_TYPE (stub) = build_int_2 (line_number, 0);
-  TREE_CHAIN (stub) = stub_list;
-  stub_list = stub;
+  tree branch_island = build_tree_list (function_name, label_name);
+  TREE_TYPE (branch_island) = build_int_2 (line_number, 0);
+  TREE_CHAIN (branch_island) = branch_island_list;
+  branch_island_list = branch_island;
 }
 
-#define STUB_LABEL_NAME(STUB)     TREE_VALUE (STUB)
-#define STUB_FUNCTION_NAME(STUB)  TREE_PURPOSE (STUB)
-#define STUB_LINE_NUMBER(STUB)    TREE_INT_CST_LOW (TREE_TYPE (STUB))
-
-/* OUTPUT_COMPILER_STUB outputs the compiler generated stub for
-   handling procedure calls from the linked list and initializes the
-   linked list.  */
-
-void
-output_compiler_stub (void)
-{
-  char tmp_buf[256];
-  char label_buf[256];
-  tree stub;
+#define BRANCH_ISLAND_LABEL_NAME(BRANCH_ISLAND)     TREE_VALUE (BRANCH_ISLAND)
+#define BRANCH_ISLAND_FUNCTION_NAME(BRANCH_ISLAND)  TREE_PURPOSE (BRANCH_ISLAND)
+#define BRANCH_ISLAND_LINE_NUMBER(BRANCH_ISLAND)    \
+               TREE_INT_CST_LOW (TREE_TYPE (BRANCH_ISLAND))
 
-  if (!flag_pic)
-    for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
-      {
-       fprintf (asm_out_file,
-                "%s:\n", IDENTIFIER_POINTER(STUB_LABEL_NAME(stub)));
+/* Generate far-jump branch islands for everything on the
+   branch_island_list.  Invoked immediately after the last instruction
+   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().  */
 
+static void
+macho_branch_islands (void)
+{
+  char tmp_buf[512];
+  tree branch_island;
+
+  for (branch_island = branch_island_list;
+       branch_island;
+       branch_island = TREE_CHAIN (branch_island))
+    {
+      const char *label =
+       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 (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
-         fprintf (asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER(stub));
+      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+       fprintf (asm_out_file, "\t.stabd 68,0,%lu\n",
+                BRANCH_ISLAND_LINE_NUMBER(branch_island));
 #endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
-
-       if (IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))[0] == '*')
-         strcpy (label_buf,
-                 IDENTIFIER_POINTER (STUB_FUNCTION_NAME (stub))+1);
-       else
-         {
-           label_buf[0] = '_';
-           strcpy (label_buf+1,
-                   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, label_buf);
-       strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
-       output_asm_insn (tmp_buf, 0);
-
+      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");
+                  
+         strcat (tmp_buf, "\tmtlr r0\n");
+  
+         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
+       {
+         strcat (tmp_buf, ":\nlis r12,hi16(");
+         strcat (tmp_buf, name_buf);
+         strcat (tmp_buf, ")\n\tori r12,r12,lo16(");
+         strcat (tmp_buf, name_buf);
+         strcat (tmp_buf, ")\n\tmtctr r12\n\tbctr");
+       }
+      output_asm_insn (tmp_buf, 0);
 #if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-       if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
-         fprintf(asm_out_file, "\t.stabd 68,0,%d\n", STUB_LINE_NUMBER (stub));
+      if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
+       fprintf(asm_out_file, "\t.stabd 68,0,%lu\n",
+               BRANCH_ISLAND_LINE_NUMBER (branch_island));
 #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
    already there or not.  */
 
-int
+static int
 no_previous_def (tree function_name)
 {
-  tree stub;
-  for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
-    if (function_name == STUB_FUNCTION_NAME (stub))
+  tree branch_island;
+  for (branch_island = branch_island_list;
+       branch_island;
+       branch_island = TREE_CHAIN (branch_island))
+    if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
       return 0;
   return 1;
 }
@@ -14803,13 +14846,15 @@ no_previous_def (tree function_name)
 /* GET_PREV_LABEL gets the label name from the previous definition of
    the function.  */
 
-tree
+static tree
 get_prev_label (tree function_name)
 {
-  tree stub;
-  for (stub = stub_list; stub; stub = TREE_CHAIN (stub))
-    if (function_name == STUB_FUNCTION_NAME (stub))
-      return STUB_LABEL_NAME (stub);
+  tree branch_island;
+  for (branch_island = branch_island_list;
+       branch_island;
+       branch_island = TREE_CHAIN (branch_island))
+    if (function_name == BRANCH_ISLAND_FUNCTION_NAME (branch_island))
+      return BRANCH_ISLAND_LABEL_NAME (branch_island);
   return 0;
 }
 
@@ -14819,13 +14864,14 @@ get_prev_label (tree function_name)
    CALL_DEST is the routine we are calling.  */
 
 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];
-  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 funname = get_identifier (XSTR (call_dest, 0));
+      tree funname = get_identifier (XSTR (operands[dest_operand_number], 0));
       
       if (no_previous_def (funname))
        {
@@ -14839,23 +14885,25 @@ output_call (rtx insn, rtx call_dest, int operand_number)
          for (; insn && GET_CODE (insn) != NOTE; insn = PREV_INSN (insn));
          if (insn)
            line_number = NOTE_LINE_NUMBER (insn);
-         add_compiler_stub (labelname, funname, line_number);
+         add_compiler_branch_island (labelname, funname, line_number);
        }
       else
        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",
-              operand_number, IDENTIFIER_POINTER (labelname));
-      return buf;
+              dest_operand_number, IDENTIFIER_POINTER (labelname));
     }
   else
-    {
-      sprintf (buf, "bl %%z%d", operand_number);
-      return buf;
-    }
+    sprintf (buf, "bl %%z%d", dest_operand_number);
+  return buf;
 }
 
-#endif /* RS6000_LONG_BRANCH */
+#endif /* TARGET_MACHO */
 
 /* Generate PIC and indirect symbol stubs.  */
 
index 5c2beea..14a42c9 100644 (file)
 
   if (GET_CODE (operands[0]) != SYMBOL_REF
       || (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)
        operands[0] = rs6000_longcall_ref (operands[0]);
 
   if (GET_CODE (operands[1]) != SYMBOL_REF
       || (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)
        operands[1] = rs6000_longcall_ref (operands[1]);
         (match_operand 1 "" "g,g"))
    (use (match_operand:SI 2 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 3 "=l,l"))]
-  "(DEFAULT_ABI == ABI_V4
-    || DEFAULT_ABI == ABI_DARWIN)
-   && (INTVAL (operands[2]) & CALL_LONG) == 0"
+  "(DEFAULT_ABI == ABI_DARWIN
+   || (DEFAULT_ABI == ABI_V4
+       && (INTVAL (operands[2]) & CALL_LONG) == 0))"
 {
   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);
 
+#ifdef TARGET_MACHO
+  return output_call(insn, operands, 0, 2);
+#else
   return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
+#endif     
 }
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
              (match_operand 2 "" "g,g")))
    (use (match_operand:SI 3 "immediate_operand" "O,n"))
    (clobber (match_scratch:SI 4 "=l,l"))]
-  "(DEFAULT_ABI == ABI_V4
-    || DEFAULT_ABI == ABI_DARWIN)
-   && (INTVAL (operands[3]) & CALL_LONG) == 0"
+  "(DEFAULT_ABI == ABI_DARWIN
+   || (DEFAULT_ABI == ABI_V4
+       && (INTVAL (operands[3]) & CALL_LONG) == 0))"
 {
   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);
 
+#ifdef TARGET_MACHO
+  return output_call(insn, operands, 1, 3);
+#else
   return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
+#endif     
 }
   [(set_attr "type" "branch,branch")
    (set_attr "length" "4,8")])
index a195d08..d8e63fb 100644 (file)
@@ -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
 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
 when the linker is known to generate glue.
 
index c7c0288..3b13c62 100644 (file)
@@ -1,6 +1,6 @@
 /* { dg-do compile { target powerpc*-*-darwin* } } */
 /* { 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.  */