user48956
user48956

Reputation: 15810

Assembly compilation error (gcc4.2.4=win, gcc4.3.3=fail)

We recently upgraded the code to gcc4.3.3 from gcc4.2.4.

void testAndSet(  volatile int*  s, int* val )
{
   __asm__ __volatile__ ( "btsl   $0, %0\n   "
           "jc   bitSet\n   "
           "movl   $0, %1\n   "
           "jmp   returnVector\n"
           "bitSet:\n   "
           "movl   $1, %1\n"
           "returnVector: " : "=m"(*s), "=m"(*val) );
}

Our code now fails with the following errors,

lock.cxx: Assembler messages:
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined
lock.cxx:59: Error: symbol `bitSet' is already defined
lock.cxx:61: Error: symbol `returnVector' is already defined

Those symbols weren't found anywhere else. (Renaming them causes the same error with the new name).

What's up with this? why do I get the errors twice?

Upvotes: 2

Views: 3005

Answers (3)

demiurg_spb
demiurg_spb

Reputation: 21

Also you may use local label names by adding %= after each local label:

"loop%=:" "\n\t"

Upvotes: 2

Adam Rosenfield
Adam Rosenfield

Reputation: 400592

This is unrelated to your error, but you could improve your code and avoid branches simply using the setCC instruction:

   __asm__ __volatile__ ( "btsl   $0, %0\n   "
       "mov $0, %1\n"
       "setc %1\n" : "=m"(*s), "=m"(*val) );

The setCC instruction (where CC is one of the condition code flags, analogous to the jCC instruction) sets a byte to 0 or 1 depending on whether or not the given condition was satisfied. Since the destination is a 4-byte value, you need to either preload it with 0 or use the MOVZX instruction to make the upper 3 bytes 0.

Upvotes: 5

user9876
user9876

Reputation: 11102

Probably the optimizer has changed and is now inlining your testAndSet() function into 2 places. Because you are using global names for your labels, this does not work. You should use local names instead. E.g:

   __asm__ __volatile__ ( "btsl   $0, %0\n   "
           "jc   0f\n   "
           "movl   $0, %1\n   "
           "jmp   1f\n"
           "0:\n   "
           "movl   $1, %1\n"
           "1: " : "=m"(*s), "=m"(*val) );

Local labels are just numbers; to disambiguate cases where there are many labels called "0" you need to use "jmp 0f" for forward jumps and "jmp 0b" for backward jumps.

Upvotes: 10

Related Questions