http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38607

sumamb <sumamb at yahoo dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |sumamb at yahoo dot com

--- Comment #16 from sumamb <sumamb at yahoo dot com> 2012-06-20 11:25:30 UTC 
---
This is a compiler problem. This issue is not generated due to the apar
IZ24688.

The g++ code is as below.
   #include 
   #include 
   using namespace std;

   template class MyClass
   {
    public:
     typedef Key KeyType;
     MyClass(KeyType aNumber)
     {
         cout << aNumber << "! = " << factorial(aNumber)
 << endl;
     }
     ~MyClass(){}
    private:
     long factorial(KeyType __x);
     long factorialHelper(KeyType __x);
   };

   template long MyClass::factorial
(KeyType __x)
   {
    if (__x <= 0) return 1;
    else return __x * factorial(__x-1);
    //else return __x * factorialHelper(__x-1);
   }

   template long MyClass::
factorialHelper(KeyType __x)
   {
    return factorial(__x);
   }

   void foo()
   {
    MyClass myClass(5);
   }




Compile with:
g++ -save-temps -shared -Wl,-G -o libshare.so share.cc


The error received will be:
ld: 0711-768 WARNING: Object share.o, section 1,
function .MyClass::factorial(int):
        The branch at address 0x36c is not followed
 by a recognized no-op
        or TOC-reload instruction. The unrecognized
instruction is 0x7C691B78.


Here is an explanation from the problem we see with a below example.


    .csect .foo[PR]
.x:    code for x...
.globl .x

.z:    nop
.y:    code for y...
.globl .y

    .csect .bar[PR]
    ...
    bl    .y

The "bl .y" and ".y:" are in different csects, so the "bl" requires an
RLD.  Note that the "bl .y" could also be written as:

    bl    .z + 4
or as
    bl    .foo[PR] + (.y - .x)

The generated code would look the same, but the corresponding RLDs
might refer to different symbols.  That is, "bl .y" would have an RLD
referring to .y, "bl .z+4" would have an RLD referring to .z, and
"bl .foo[PR] + (.y-.x)" would have an RLD referring to .foo[PR].

In the g++ example above, the -G linker flag causes glink code to be used
for all function calls to exported symobls.  These calls need to be
followed by a TOC reload instruction.  If .y were not exported, no
warning would occur.

There are a few possible compiler fixes:

1)    Use ".lglobl .y" instead of ".globl .y"  This will keep .y from
    being exported.
2)    Add another label at the same address and use .lglobl with the
    label.  (The assembler could do this, but it would change the
    behavior of the program, because .y would no longer be superceded by
    the runtime linker.

.y:    
    .globl .y
.y_local: .lglobl .y_local
    ...
    bl    .y_local

Since .y_local cannot be exported, no nop instruction is needed after "bl".

Finally, it is possible for the compiler source code to be:

    .csect .foo[PR]
    ...
.y:    
    ...
    .csect .bar[PR]
    ...
    bl    .y

In this case, .y is not in the output symbol table at all, so the RLD
must refer to the csect .foo[PR].  If this symbol is global and
exported, a warning will still be seen for the missing nop.
Regardless, if branch overflow occurs, this particular branch might
not be able to be fixed up.

Reply via email to