While profiling a program compiled with gcc, I noticed functions like foo.isra.3. What does isra indicate? I notice that one of the functions is only called in a few places, and one of the arguments is always specified as a literal value. Maybe it means it's a variant of the function optimised for certain arguments?
According to a comment on this bug report (and similar comments I could find):
ISRA is the name of the variable that gets created by IPA SRA ...
IPA SRA is an optimization option:
-fipa-sra
Perform interprocedural scalar replacement of aggregates, removal of unused parameters and replacement of parameters passed by reference by parameters passed by value.
Enabled at levels -O2, -O3 and -Os.
So most likely, it's a version of a function with those optimizations.
In the case you mentioned, it's possible that it's replacing a pass-by-reference with a pass-by-value since it knows there's no point to passing a literal by reference.
Related
Normally I compile with flags that discard all variables that are never used (using -fdata-sections). But sometimes, I need to include a variable into a special section and I want that variable to never be optimized away even if it is not used.
How can I tell gcc linker (using attributes perhaps?) that it can under no circumstances discard a specific variable?
I'm particularly curious about LLVM 4.1, but would be interested in other compilers' behavior as well.
According to the GCC documentation (which LLVM supports at least in part), the unused attribute has the following behavior:
This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC will not produce a warning for this variable.
If the compiler is able to warn you about unused parameters and variables, though, presumably it already knows what parameters and variables are unused without you having to tell it (especially since the unused attribute only indicates that the variable is possibly unused). Therefore, does the unused attribute allow the compiler to perform any additional optimizations, or is its purpose just to allow for more readable code? Also, if the unused attribute does in fact allow the compiler to perform additional optimizations, what happens if you actually end up using a parameter or variable that was specified as unused? LLVM (in XCode) did not seem to complain about this case, though it's possible I wasn't compiling at the right optimization level or with the right warnings enabled.
__attribute__((unused)) doesn't help optimization, and it doesn't mean that the value is necessarily unused. It suppresses warning (if there is a reason for this warning, that is, if the value is indeed unused), that's all.
When compiling fortran code into object files: how does the compiler determine the symbol names?
when I use the intrinsic function "getarg" the compiler converts it into a symbol called "_getarg#12"
I looked in the external libraries and found that the symbol name inside is called "_getarg#16" what is the significance of the "#[number]" at the end of "getarg" ?
_name#length is highly Windows-specific name mangling applied to the name of routines that obey the stdcall (or __stdcall by the name of the keyword used in C) calling convention, a variant of the Pascal calling convention. This is the calling convention used by all Win32 API functions and if you look at the export tables of DLLs like KERNEL32.DLL and USER32.DLL you'd see that all symbols are named like this.
The _...#length decoration gives the number of bytes occupied by the routine arguments. This is necessary since in the stdcall calling conventions it is the callee who cleans up the arguments from the stack and not the caller as is the case with the C calling convention. When the compiler generates a call to func with two 4-byte arguments, it puts a reference to _func#8 in the object code. If the real func happens to have different number or size of arguments, its decorated name would be something different, e.g. _func#12 and hence a link error would occur. This is very useful with dynamic libraries (DLLs). Imagine that a DLL was replaced with another version where func takes one additional argument. If it wasn't for the name mangling (the technical term for prepending _ and adding #length to the symbol name), the program would still call into func with the wrong arguments and then func would increment the stack pointer with more bytes than was the size of the passed argument list, thus breaking the caller. With name mangling in place the loader would not launch the executable at all since it would not be able to resolve the reference to _func#8.
In your case it looks like the external library is not really intended to be used with this compiler or you are missing some pragma or compiler option. The getarg intrinsic takes two arguments - one integer and one assumed-sized character array (string). Some compilers pass the character array size as an additional argument. With 32-bit code this would result in 2 pointers and 1 integer being passed, totalling in 12 bytes of arguments, hence the _getarg#12. The _getarg#16 could be, for example, 64-bit routine with strings being passed by some kind of descriptor.
As IanH reminded me in his comment, another reason for this naming discrepancy could be that you are calling getarg with fewer arguments than expected. Fortran has this peculiar feature of "prototypeless" routine calls - Fortran compilers can generate calls to routines without actually knowing their signature, unlike in C/C++ where an explicit signature has to be supplied in the form of a function prototype. This is possible since in Fortran all arguments are passed by reference and pointers are always the same size, no matter the actual type they point to. In this particular case the stdcall name mangling plays the role of a very crude argument checking mechanism. If it wasn't for the mangling (e.g. on Linux with GNU Fortran where such decorations are not employed or if the default calling convention was cdecl) one could call a routine with different number of arguments than expected and the linker would happily link the object code into an executable that would then most likely crash at run time.
This is totally implementation dependent. You did not say, which compiler do you use. The (nonstandard) intrinsic can exist in more versions for different integer or character kinds. There can also be more versions of the runtime libraries for more computer architectures (e.g. 32 bit and 64 bit).
I want to do something similar to how, in GCC, you can do syntax checking on printf-style calls (to make sure that the argument list is actually correct for the call).
I have some functions that take a variable number of parameters. Rather than enforce what parameters are sent, I need to ensure that the last parameter passed is a NULL, regardless of how many parameters are passed-in.
Is there a way to get GCC to do this type of syntax check during compile time?
You probably want the sentinel function attribute, so declare your function like
void foo(int,double,...) __attribute__((sentinel));
You might consider customizing your GCC with a plugin or a MELT extension to typecheck more precisely your variadic functions. That is, you could extend GCC with your own attributes which would do more precise checks (or simply make additional checks based on the names of your functions).
The ex06/ example of melt-examples is doing a similar check for the jansson library; unfortunately that example is incomplete today October 18th 2012, I am still working on it.
In addition, you could define a variadic macro to call such a function by always adding a NULL e.g. something like:
#define FOO(N,D,...) foo((N),(D),##__V_ARGS__,NULL)
Then by coding FOO(i+3,3.14,"a") you'll get foo((i+3),(3.14),"a",NULL) so you are sure that a NULL is appended.
Basile Starynkevitch is right, go with a function attribute. There are a ton of other useful function attributes, like being able to tell the compiler "If the caller doesn't check the return value of this function, it's an error."
You may also want to see if splint can check for you, but I don't think so. I think it would have stuck in my memory.
If you haven't read over this page of GCC compiler flags, do that, too. There are a ton of handy checks in there. http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
I have a question regarding gcc. Why I get an error of unused variable when I define the variable locally in a function but not when the variable is global in a unique file?.
I can understand that it can be use for someone else, but to do that then I need to put the external word right?
Thanks in advance.
The compiler has no way of knowing if a global variable is used - it could be used from a compilation unit written in a completely different language, for example.
If by "global in a unique file", you mean "int x;" outside of any function, the it's not the compilers job to detect that, the variable needs to be available to the linker in case another compilation unit needs it (such as errno).
If you meant "static int x" where it's not made available to the linker, this is probably just a choice made by GCC. I don't believe compilers are required to notify of this and it does no real damage other than wasting a few bytes in your address space.
Because global variables can be used on any other place that the compiler cannot known. For instance on a external library o program.
Unused locals can be determined by the compiler. Unused globals can only be determined by the linker, since they can be shared across object files.
In general, the linker doesn't do warnings for code-gen.
When the variable is global, the compiler has not full visibility across all the compilation units in the project - the variable could be modified in another compilation unit. The linker is able to tell that it is unused, probably it will remove it from the object file.
Because if it's global it can be used by another module that gets linked in later.
It's a common idiom to have all your globals defined in a single file. That file may not even have any code, much less code that uses all the variables.
I have encountered the same question when I build the dalvikVM in android2.3 and I got the key of the point. It is because that the parameters of the compiler is too strict:
LOCAL_CFLAGS += -Werror.