On 08/19/2010 11:33 AM, Job Noorman wrote: > On Thursday 19 August 2010 11:19:09 you wrote: >> On 08/19/2010 09:10 AM, Job Noorman wrote: >>> Andrew Haley <aph at redhat dot com> wrote: >>>> Pretty obviously, replacing "movl $_ZN3Foo6foobarEv, %eax; push %rax" >>>> with "push $_ZN3Foo6foobarEv" is an optimization. >>> >>> Yes, it would be if GCC does it without my help (which, by the way, it >>> does not, no matter which optimizations used). However, since I'm >>> explicitly telling GCC to emit "push $_ZN3Foo6foobarEv", it is an >>> optimization from my side and should have nothing to do with any >>> optimizations from GCC's side. >> >> "should" statement with missing "because": syntax error. :-) >> >>>> And nothing that a gcc developer says will convince you otherwise? >>> >>> Nothing a GCC developer has already said has convinced me. Of course >>> I can be convinced. >>> >>>> If I were you, I'd use >>>> >>>> void test() >>>> { >>>> >>>> asm("push %0;" >>>> >>>> : "g"((plain_foobar_t)&Foo::foobar)); >>>> >>>> } >>> >>> That will output the exact same assembly code as when using the "r" >>> constraint. I really want to use the "i" constraint to skip the extra >>> "mov". >> >> Works for me: >> >> -O0: >> >> movl $_ZN3Foo6foobarEv, %eax >> #APP >> # 13 "ttt.cc" 1 >> push %rax; >> # 0 "" 2 >> #NO_APP >> >> -O2: >> >> #APP >> # 13 "ttt.cc" 1 >> push $_ZN3Foo6foobarEv; >> # 0 "" 2 >> #NO_APP >> >>> And, sorry if I sound like a broken record, I still think this should be >>> possible. Consider the following (which was pointed out to me in a >>> comment on >>> >>> my bug report): >>> void test() >>> { >>> >>> asm("push %0;" >>> >>> : "i"((void*)(plain_foobar_t)&Foo::foobar)); >>> >>> } >>> >>> This always works! Now, if you could give me a good explanation of how it >>> could be that "(void*)expr" is accepted as a constant expression when >>> "expr" is not, >> >> I already did, I think: some things get constant folded regardless of >> optimization level, but this is just luck. >> >>> I might be convinced that this is not a bug. >> >> But gcc doesn't support the "i" constraint with anything other than a >> real compile-time constant (in the sense of __builtin_constant_p) so >> it's not a bug. > > Hi Andrew, Hi, > About your last statement: That would make sense to me. (Although I really > don't like the fact that whether something would be accepted by the "i" > constraint depends on optimization options. IMHO, whether something is > syntactically valid should not depend on optimizations.) It's not syntactically invalid, it's semantically invalid. It's always semantically invalid. > But I see some evidence that your statement is not true. First of all, it's > not what the documentation claims: > > " 'i': An immediate integer operand (one with constant value) is allowed. This > includes symbolic constants whose values will be known only at assembly time > or later. " Hmm, this seems to generalize "i" to symbolic constants, but not to expressions that yield addresses. > Secondly, in practice a lot of expression are accepted which are not > __builtin_constant_p. Here is an example program: > > #include <iostream> > using namespace std; > > struct Foo {void foobar() {}}; > typedef void (*plain_foobar_t)(Foo*); > void func() {} > int var; > > int main() > { > cout << __builtin_constant_p((void*)(plain_foobar_t)(&Foo::foobar)) > << __builtin_constant_p(func) > << __builtin_constant_p(&var) << endl; > > asm("" : : "i"((void*)(plain_foobar_t)(&Foo::foobar)), > "i"(func), > "i"(&var)); > } > > This compiles without errors at -O0 but prints "000". > > So, if your statement is true, don't you think there is something weird going > on here? This is a fundamental part of language definition: a translator is not required to do anything in particular with a program that has undefined behaviour. One of the options a translator has is to do what the user expected. Sometimes an operand that is not a constant may work with the "i" constraint. This is because a pass in gcc propagated a constant through an expression. gcc is allowed to do this. However, gcc is not required to do this. Finally, does the "g" constraint really not work for you with a recent gcc? Andrew.