Optimization breaks inline asm code w/ptrs

David Wohlferd dw@LimeGreenSocks.com
Sun Aug 13 04:24:00 GMT 2017


Environment:
gcc 6.1
compiling for 64bit i386
optimizations: -O2

Consider this simple bit of code (from 
https://stackoverflow.com/a/45656087/2189500):

#include <stdio.h>

int getStringLength(const char *pStr){

     int len;

     __asm__  (
         "repne scasb\n\t"
         "not %%ecx\n\t"
         "dec %%ecx"
         :"=c" (len), "+D"(pStr)
         :"c"(-1), "a"(0)
     );

     return len;
}

int main()
{
    char buff[50] = "hello world";
    int a = getStringLength(buff);
    printf("%s: %d\n", buff, a);
}

This code works as expected and prints out 11.  Yay.

However, if you add "buff[4] = 0;" before the call to getStringLength, 
it STILL prints out 11 (when optimizations are enabled), when it should 
print 4.

I would expect this kind of behavior if the asm were in 'main.' But it 
has always been my understanding that function calls performed an 
implicit memory clobber.  The fact that this clobber goes away during 
inlining means that code can stop working any time the compiler makes a 
different decision about whether or not to inline a function.  Ouch.

And before somebody asks:  Adding "+m"(pStr) does not help.

The result is that (apparently) you can NEVER safely pass a buffer 
pointer to inline asm without using the memory clobber.  If this is 
true, I don't believe it is widely known.

Given how 'heavy' memory clobbers are, I would hope that only pointers 
that have 'escaped' the function would get flushed before a function 
call.  But not flushing *anything* seems very bad.

dw



More information about the Gcc mailing list