On Thursday 21. December 2017 00.08.09 Paul Boddie wrote:
> On Wednesday 20. December 2017 14.46.12 James Cowgill wrote:
> > It would be useful to have a reduced .c file which can reproduce this
> > bug and then decide if its a bug in gcc or binutils.
> 
> The offending program is this one:
> 
> https://svn.l4re.org/repos/oc/l4re/trunk/l4/pkg/examples/sys/utcb-ipc/main.c

I've been trying to work towards identifying the code that might cause the 
problem, but progress has been slower than desired. What happens is that a 
macro (L4UTIL_THREAD_STATIC_FUNC) is employed to add a kind of wrapper 
function around an existing function:

L4UTIL_THREAD_STATIC_FUNC(thread2)
{
  /* thread2 function body */
}

It looks like this when expanded by hand:

EXTERN_C_BEGIN
void __attribute__((visibility("internal"))) thread2(void);
static void __attribute__((used)) thread2_worker_function(void);
asm (
  ".type thread2, function \n"
  "thread2 : \n .set push; .set noreorder;"
  L4UTIL_THREAD_START_SETUP_GP
  "la $t9, thread2_worker_function\n"
  "  jal $t9 \n"
  "   nop    \n"
  ".set pop"
);
EXTERN_C_END
static L4_NORETURN void thread2_worker_function(void)
{
  /* thread2 function body */
}

It seems that the problem is caused by the declaration of thread2 involving 
the visibility attribute:

void __attribute__((visibility("internal"))) thread2(void);

If I replace that declaration with this (as it used to be)...

static void thread2(void);

...the error associated with the output goes away (although I get a warning 
from the compiler about thread2 not being defined, which happens in the 
assembly language code, of course).

Changing the visibility type of thread2 to any of the other acceptable values 
("default", "hidden", and so on) does not eliminate the error. Only using a 
static qualifier does so.

The actual code added for the wrapper function isn't so interesting - I guess 
it has to set up t9 to let position-independent code work, which is actually 
something I had to change elsewhere in L4Re when compiling with gcc - but I 
wonder if the introduction of the assembly language object confuses the 
compiler in some way.

Meanwhile, if I put the core of the assembly language within a function, like 
this...

void __attribute__((visibility("internal"))) thread2(void)
{
  asm (
    ".set push; .set noreorder;"
    L4UTIL_THREAD_START_SETUP_GP
    "la $t9, thread2_worker_function\n"
    "  jal $t9 \n"
    "   nop    \n"
    ".set pop"
  );
}

...the error is also avoided. Of course, various extra instructions get 
generated for this wrapper function, which is probably what the assembly 
language definition of a function is meant to avoid, but the register 
initialisation and invocation of the "real" function are probably still 
correct.

So might it be the case that the assembly language definition gets "lost" 
somewhere? Sorry not to be more specific about this: I don't usually have to 
debug compilers other than my own!

Paul

Reply via email to