This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: effect of -fPIC on code speed


[again as plain text, slightly augmented]

 

>> It's actually part of the C standard: there may only be one definition 
>> of any symbol, whether that symbol refers to a function or to data. So, 
>> for every visible symbol X in a program, &X must be the same, no matter 
>> who is asking. 

>> All manner of things break without this. 



Some stuff breaks, but not much.
It's pretty rare to compare the addresses of globals/functions for equality.
This rule is sometimes broken on Windows, and it is rarely noticed/discussed.
E.g. if you import a function but don't mark it as __declspec(dllimport), or if you "static/const-ly" take the address of a __declspec(dllimport) (gets a warning about this vary thing).

windows.h uses __declspec(dllimport) pretty rigorously, so the tendency is to follow the rule.
But it is easy to break.
 
2.c:


#include <stdio.h>

void CreateFileA(void);
__declspec(dllimport) void CreateFileW(void);

void* p = &CreateFileA;
void* q = &CreateFileW;

__declspec(dllexport) void MyDll()
{
printf("2: a:%p w:%p m:%p a2:%p w2:%p\n", &CreateFileA, &CreateFileW, MyDll, p, q);
}


1.c

#include <stdio.h>
void CreateFileA(void);
__declspec(dllimport) void CreateFileW(void);
void MyDll();

void* p = &CreateFileA;
void* q = &CreateFileW;

int main()
{
MyDll();
printf("1: a:%p w:%p m:%p a2:%p w2:%p\n", &CreateFileA, &CreateFileW, MyDll, p, q);
return 0;
}

c:\>cl -LD 2.c
c:\>cl 2.lib 1.c
1.c : warning C4232: nonstandard extension used : 'q' : address of dllimport 'CreateFileW' is not static, identity not guaranteed
c:\>.\1
2: a:000007FEFC338A9E w:0000000077AE2A30 m:000007FEFC331000 a2:000007FEFC338A9E w2:000007FEFC338A98
1: a:000000013F9185BE w:0000000077AE2A30 m:000000013F911050 a2:000000013F9185BE w2:000000013F9185B8


See how "w" uses the usual declaration and does meet the rule, or gets a warning, and the rest don't.
__declspec(dllimport) I think of as just a nice micro optimization but I guess it is also good for a) generally making this rule more upheld b) causing a warning when the warning is also then violated.

 
If you don't need identity, it is easy to fix the warning with a wrapper function.
static void MyFoo() { foo(); }
void (*pfoo) = MyFoo; /* instead of foo */
 
 
Of course, such small functions may be prone to break the rule "the other way around" under over-aggressive optimization. That is:
 
  static void MyFoo() { foo(); }   
  static void MyBar() { foo(); }   

 
   assert(&MyFoo != &MyBar);  ?
 
 
The Visual C++ linker also has "identical comdat" folding.
 
 
 template <typename T> T max(T,T); 
 
 assert(&max<int> != &max<long>); ?  
 

- Jay


(as well, something like LTCG/LTO could make the annotations not needed but always get the optimization/conformance "for free" (for no additional cost)) 		 	   		  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]