GCC __attribute__((always_inline)) and lambdas, is this syntax correct? - gcc

I am using GCC 4.6 as part of the lpcxpresso ide for a Cortex embedded processor. I have very limited code size, especially when compiling in debug mode. Using attribute((always_inline)) has so far proven to be a good tool to inline trivial functions and this saves a lot of code bloat in debug mode while still maintaining readability. I expect it to be somewhat mainstream and supported in the future because it is mentioned here http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0348c/CIAJGAIH.html
Now to my question: Is this the correct Syntax for declaring a Lambda always inline?
#define ALWAYS_INLINE __attribute__((always_inline))
[](volatile int &i)ALWAYS_INLINE{i++;}
It does work, my question is will it continue to work in future and what can I do to ensure it works in the future. If I ever switch to another major compiler that supports c++11 will I find a similar keyword which I can replace the attribute((always_inline)) with?
If I were to meet my fairy godmother I would wish for a compiler directive which causes all lambdas which are constructed as temporaries with empty constructors and bound by reference to be automatically inlined even in debug mode. Any ideas?

Will it continue to work in future?
Likely but, always_inline is compiler specific and since there is no standard specifying its exact behavior with lambda, there is no guaranty that this will continue to work in the future.
What can I do to ensure it works?
This depends on the compiler not you. If a future version drops support for always_inline with lambda, you have to stick with a version that works or code your own preprocessor that inlines lambdas with an always_inline-like keyword.
If I ever switch to another major compiler that supports c++11 will I
find a similar keyword?
Likely but again, there is no guaranty. The only real standard is the C++ inline keyword and it is not applicable to lambdas. For non-lambda it only suggests inlining and tells the compiler that a function may be defined in different compile units.

Related

Where is __builtin_va_start defined?

I'm trying to locate where __builtin_va_start is defined in GCC's source code, and see how it is implemented. (I was looking for where va_start is defined and then found that this macro is defined as __builtin_va_start.) I used cscope -r in GCC 9.1's source code directory to search the definition but haven't found it. Can anyone point where this function is defined?
That __builtin_va_start is not defined anywhere. It is a GCC compiler builtin (a bit like sizeof is a compile-time operator). It is an implementation detail related to the <stdarg.h> standard header (provided by the compiler, not the C standard library implementation libc). What really matters are the calling conventions and ABI followed by the generated assembler.
GCC has special code to deal with compiler builtins. And that code is not defining the builtin, but implementing its ad-hoc behavior inside the compiler. And __builtin_va_start is expanded into some compiler-specific internal representation of your compiled C/C++ code, specific to GCC (some GIMPLE perhaps)
From a comment of yours, I would infer that you are interested in implementation details. But that should be in your question
If you study GCC 9.1 source code, look inside some of gcc-9.1.0/gcc/builtins.c (the expand_builtin_va_start function there), and for other builtins inside gcc-9.1.0/gcc/c-family/c-cppbuiltin.c, gcc-9.1.0/gcc/cppbuiltin.c, gcc-9.1.0/gcc/jit/jit-builtins.c
You could write your own GCC plugin (in 2Q2019, for GCC 9, and the C++ code of your plugin might have to change for the future GCC 10) to add your own GCC builtins. BTW, you might even overload the behavior of the existing __builtin_va_start by your own specific code, and/or you might have -at least for research purposes- your own stdarg.h header with #define va_start(v,l) __my_builtin_va_start(v,l) and have your GCC plugin understand your __my_builtin_va_start plugin-specific builtin. Be however aware of the GCC runtime library exception and read its rationale: I am not a lawyer, but I tend to believe that you should (and that legal document requires you to) publish your GCC plugin with some open source license.
You first need to read a textbook on compilers, such as the Dragon book, to understand that an optimizing compiler is mostly transforming internal representations of your compiled code.
You further need to spend months in studying the many internal representations of GCC. Remember, GCC is a very complex program (of about ten millions lines of code). Don't expect to understand it with only a few days of work. Look inside the GCC resource center website.
My dead GCC MELT project had references and slides explaining more of GCC (the design philosophy and architecture of GCC changes slowly; so the concepts are still relevant, even if individual details changed). It took me almost ten years full time to partly understand some of the middle-end layers of GCC. I cannot transmit that knowledge in a StackOverflow answer.
My draft Bismon report (work in progress, funded by H2020, so lot of bureaucracy) has a dozen of pages (in its sections ยง1.3 and 1.4) introducing the internal representations of GCC.

Localize g++ compile options within code

I'm looking for a simple way to localize certain g++ (g++-4.9 to be specific) compile options to certain lines of code or at least targeted functions. I'm interested generally speaking, but also specifically to the -fast-math, -ffinite-math-only and -fno-signed-zeros options.
I presume that localization at the *.cpp file level is possible with make utility, but I'm hoping there is a way to enable it in the code itself, through #pragma or __attribute__ or something. I want to do this not only to minimize dependencies to external files (i.e. risk of incorrect makefile) but also to hopefully hyperlocalize certain FP behavior to specific equations within a function.
Alternatively, if localization of FP behavior by inline directives is NOT possible, what can I do to at least trigger a compile time error if desired compiler directive is NOT enabled in project build (e.g. makefile is lost or inappropriately modified).
I would presume that such inline optimization might be compiler specific, g++ in this case, but that is a compromise I'm willing to take.
In gcc you can use function attribute optimize:
void f () __attribute__ ((optimize("fast-math"), optimize("finite-math-only"), optimize("no-signed-zeros")));
I'm not sure that you are using the "localize" word correctly. Localization is related to adapting software to users of different human languages (French, Russian, Chinese...)
Perhaps you want to ask the compiler to optimize some functions with other optimization flags.
This is possible using #pragma GCC optimize etc... or using some function attributes
You might be able to turn on some bits of this with the fpmath option in a function attribute, but this was not clear to me from the docs. In light of that, I will focus on detection instead:
-fast-math already turns on -ffinite-math-only, so you don't need to worry about that. The docs for -fast-math say:
This option causes the preprocessor macro FAST_MATH to be
defined.
Which means it can be detected via
#ifndef __FAST_MATH__
#error "The -fast-math compiler option is required"
#endif
I have not yet found a compile-time way to detect the presence of -fno-signed-zeros

Freestanding GCC and builtin functions

The GCC docs at http://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html say (under -ffreestanding) that a freestanding environment implies -fno-builtin. I might be misunderstanding exactly what a freestanding environment is or how it works, but it seems to me that, since the builtins usually emit inline code instead of calling the library function, this is ideal for a freestanding environment where the standard library may be missing functionality or even missing entirely.
So why would we not want to use the biltins with a freestanding environment?
In freestanding mode the compiler can not rely on semantical considerations.
Most builtins in GCC work silently -- for instance the compiler sees that you are using strcpy() and in hosted mode it may guess that, when you are using strcpy(), you are intending exactly to copy a string. Then it may replace strcpy with an extensionally equivalent builtin, which is better for the given target to copy a string.
In freestanding mode, using strcpy() function means ANYTHING. The idea is just not the standard library absence in linkage. The idea of freestanding mode is that there is no standard library even on definition level, except float.h, iso646.h, limits.h, stdarg.h, stdbool.h, stddef.h, stdint.h (C99 standard 4.6). You may in freestanding mode decide to format your hard drive with strcpy, and this is perfectly legal for the C language. The compiler thus don't know how to use builtins, and it declines to use them at all.

GCC technical details

I don't know if this is the right place for things like this, but I am curious about a few aspects of the GCC front-end/back-end architecture:
I know I can compile .o files from C code and link them to C++ code, and I think I can do it the other way round, too. Does this work because the two languages are similar, or because the GCC back-end is really language-independent? Would this work with ADA code too? (I don't even know if that makes sense, since I don't know ADA or if it even has "functions", but the question is understood. If it makes no sense, think "Pascal" or even "my own custom language front-end")
Where would garbage-collection be implemented? For example, a Java front-end. The way I understand, if compiling to a JVM back-end, the "platform" will take care of the GC, and so the front-end needs not do anything about it, but if compiling to native code, would the front-end send garbage-collecting GENERIC code to the back-end, or does it turn on some flag telling the back-end to produce garbage-collecting code? The first makes more sense to me, but that would mean the front-end produces different output based on the target, which seems to miss the point of the GCC's front-end/back-end architecture.
Where would language-specific libraries go? For instance, the standard Java classes or standard C headers. If they are linked in at the end, then could a C program theoretically call functions from the Java library or something like that, since it is just another linked library?
Yes, the backend is at least reasonably language independent. Yes, it works with Ada.
GCJ generates native code which uses a runtime library. The garbage collector is part of the runtime library.
GCJ implements the CNI, which allows you to write code in C++ that can be used as native methods by Java code -- but being able to do this is a consequence of them having designed it in, not just an accidental byproduct of using the same back-end.
It is possible because calling convention is compatible, but name mangling is different (no mangling in C). To call C function from C++ you should declare it with extern "C". And to call C++ function from C you should declare it with mangled name (and may be with additional or different type args). The calling Fortran code is possible in some cases too, but argument passing convention is different (pass by ref in Fortran).
There were actually a converters from C++ to C (cfront) and from fortran to c (f2c) and some solutions from them are still used.
garbage-collection is implemented in run-time library, e.g. boehm. Backend should generate objects compatible with selected GC library.
Compiler driver (g++, gfortran, ..) will add language-specific libraries to linking step.

GCC 4.7 fails to inline with message "function body not available"

I am trying to compile some legacy code with more modern toolchains. I have tracked down one of my issues to the switch from gcc 4.6 to gcc 4.7:
Some of the functions are annotated with the inline keyword. Gcc fails on these with the error message:
error: inlining failed in call to always_inline 'get_value_global': function body not available
What is the correct way of dealing with this issue? How could the function body not be available? Should the compiler not make sure that it is available in all situations that require it?
Edit
As requested (in a deleted comment), an example of a signature of a function resulting in the error:
inline struct a_value_fmt const *find_a_value_format(struct base_fmt *base)
{
/* the code */
}
That error is typical to inline functions declared in source files, rather than in header files, in which case the compiler is not able to inline them (as the code of the function to be inlined must be visible to the compiler in the same source file being compiled). So, first thing I would check is that all functions declared inline are indeed defined in header files.
It may be that a change in GCC diagnostics in 4.7 caused the error to surface, and that it went silent in GCC 4.6 (but that's just a speculation).
The quoted error indicates that the function is declared with __attribute__((always_inline)). Note that GCC may fail to inline and report a different (and quite obscure) error if function is declared always_inline, but not with the inline keyword - so make sure that any function declared as always_inline is also declared as inline.
Few more tips:
General advice, which may not be applicable: since this is a legacy codebase, you may want to re-evaluate which functions should be inlined, being on the critical path, and which aren't, based on updated profiling results. Sometimes, inline is used generously, even when it is not required, or redundant. In some cases, the fix may be to remove the inline keyword in places where it is not needed.
When functions are declared in header files, the compiler considers them for inlining automatically (given they are small enough, and the compiler thinks that inlining them will improve performance, based on its heuristics) - even when the inline keyword is not used. inline is sort of a "recommendation" to the compiler, and it doesn't have to obey (unless it is given along with the always_inline attribute).
Modern compilers make relatively smart inlining decisions, so it's usually best to let the compiler do it's thing, and declare functions as inline (and moving their implementations to header files) in the appliation hot spots, based on profiling results.

Resources