This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Blackfin patch: fix sibcalls & ID shared libraries interaction

There's a bug in the Blackfin backend that can cause the wrong value to
end up in the PIC register with -mid-shared-library.

GCC tries to be clever about reloading P5 in function prologues: if it
knows that a function is local to a file, then it does not need to
reload P5: every possible caller will already have loaded the proper
value in its own prologue.

This optimization is all fine and good, but it doesn't take into account
that a local function may be called as a sibcall - take this example:

        [--sp] = ( p5:5 );

        LINK 12;
        P5 = [P5+_current_shared_library_p5_offset_];
        R1 = [P5+___malloc_heap@GOT];
        P2 = [P5+_free_to_heap@GOT];
        ( p5:5 ) = [sp++];

        jump (P2);

free_to_heap() is a local function, so it does not reload P5 - but the
epilogue of free() has already popped the old value of P5, so it has the
wrong value during free_to_heap().

Fixed with this patch.  Two possible options - just make local functions
reload P5, or disable sibcalls in some cases.  I've done the latter.
Committed as 119013.


Index: ChangeLog
--- ChangeLog	(revision 119012)
+++ ChangeLog	(working copy)
@@ -25,6 +25,9 @@
 	(TARGET_SWITCHES): Add -mleaf-id-shared-library and -msep-data.
 	* doc/invoke.texi (Blackfin Options): Document new switches.
+	* config/bfin/bfin.c (bfin_function_ok_for_sibcall): Handle some
+	edge cases with local functions and TARGET_ID_SHARED_LIBRARY.
 2006-11-19  Andrew Pinski  <>
 	PR rtl-opt/29879
Index: config/bfin/bfin.c
--- config/bfin/bfin.c	(revision 119012)
+++ config/bfin/bfin.c	(working copy)
@@ -1596,7 +1596,28 @@ bfin_function_ok_for_sibcall (tree decl 
 			      tree exp ATTRIBUTE_UNUSED)
   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
-  return fkind == SUBROUTINE;
+  if (fkind != SUBROUTINE)
+    return false;
+    return true;
+  /* When compiling for ID shared libraries, can't sibcall a local function
+     from a non-local function, because the local function thinks it does
+     not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
+     sibcall epilogue, and we end up with the wrong value in P5.  */
+  if (!flag_unit_at_a_time || decl == NULL)
+    /* Not enough information.  */
+    return false;
+  {
+    struct cgraph_local_info *this_func, *called_func;
+    rtx addr, insn;
+    this_func = cgraph_local_info (current_function_decl);
+    called_func = cgraph_local_info (decl);
+    return !called_func->local || this_func->local;
+  }
 /* Emit RTL insns to initialize the variable parts of a trampoline at

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]