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. */
}
}
-#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. */
{
}
#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;
}
/* 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;
}
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))
{
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. */
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")])