Inline functions

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
Gonzo
Posts: 722
Joined: Dec 11, 2005 22:46

Inline functions

Post by Gonzo »

I think freebasic would benefit inline functions, just like in C++
It offers so much with no drawbacks, unless you start inlining big functions of course =)

I see many people on the forums using big #macros, when inline does the same thing without being hard to debug
Inline also offers you the chance to 'return' a value

Some examples:
inline empty constructor: avoid function call for class with multiple constructors where the default one does nothing

inline getters:
they're just one line, so no need for function call

and this will still show up as "call" in debugger, which is great

Can FB do automatic inlining, considering implentations are in the modules?
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: Inline functions

Post by dkl »

A kind of inlining has been on my to-do list for fbc for a long time, would be cool to have it. I was thinking that if an Inline keyword is added, it should be guaranteed inlining -- i.e. type-safe macros, not like C/C++ where it depends on compiler heuristics, attributes, optimization options etc.

It must be noted that fbc can't currently change generated code at link-time, and by design only looks at one module at a time, changing that would be difficult and, I think, wrong.

Thus, if FB allowed Public Inline procedures, the inlining could only happen in the module containing the body, and the body would have to be preserved in case it's called by other modules. Of course the programmer could work around that by putting Private Inline procedures in a header file and #including that into each module (that'd be much like C++ I think), to get inlining in all modules.

Then perhaps there's no point allowing Public Inline at all, and instead Inline could be 3rd option besides Private/Public, meaning private+inlining.

Without (or besides) that it'd also be possible to do automatic inlining based on some simple heuristic (such as every procedure with only 1 statement can be inlined). However I'm not sure that'd be wise to just do it automatically starting with some FB version, because it'd be totally unexpected by the programmers. Thus perhaps another keyword such as MayInline or something would have to be used for something like that.

I have no idea how debugging would work. It could surely show the file name/line numbers where the inlined code came from, unlike with preprocessor macros, but besides that I don't know whether there's actually a way to somehow represent inlined function calls in the STABS format.
gothon
Posts: 225
Joined: Apr 11, 2011 22:22

Re: Inline functions

Post by gothon »

In theory it should be possible to make llvm perform an inlining optimization pass on the program after it has been linked. That is if every module is compiled to llvm bit-code, then linked by the llvm linker. However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done. Still it makes for less linking issues. We could perhaps look into it after the llvm back-end becomes stable.
fxm
Moderator
Posts: 12082
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Inline functions

Post by fxm »

I think the simpler is that the compiler does not inline a function if (not exhaustive list):
- the function or its caller is compiled with option for debug,
- the function has a variable argument list,
- the function is recursive,
- the function is called virtually,
- the call is made via a function pointer.
jevans4949
Posts: 1186
Joined: May 08, 2006 21:58
Location: Crewe, England

Re: Inline functions

Post by jevans4949 »

Of course it already exists in other BASICs: DEF FN.
Gonzo
Posts: 722
Joined: Dec 11, 2005 22:46

Re: Inline functions

Post by Gonzo »

gothon wrote:However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done.
I don't think you can do that, because inline functions need to be exposed to the code that uses it.
It's basically just an insertion operation, probably after preprocess and just before code validation
It's definitely not possible in gcc which I've used extensively :)

I wonder why I wrote about inline operations from modules to begin with.. it does complicate things for compiler programmers and even the users themselves, since "correctly" implemented IDEs will not pick up functions hidden from you

jevans, I don't think DEF FN can inline constructors or member functions :)

Also are you guys thinking about using a more robust error/throw-catch system like there is in Java, .NET and C++?
There is good support for debugging this, in gcc "catch throw"
I'm not a big fan of throwing from constructors, since it sometimes bites you in the ass when you create objects passed directly to functions since you cannot regain the lost memory
Or, at the very least if you create 2 objects, the first constructed correctly into free store and the second throws

Is this something that is interesting for you all?
How would you implement it?
dkl
Site Admin
Posts: 3235
Joined: Jul 28, 2005 14:45
Location: Germany

Re: Inline functions

Post by dkl »

Personally I'm not interested in adding exceptions to FB. FB is native code, the only way to add exceptions would be to do it exactly like GCC does for C++ (DWARF and/or setjump/longjump), and that comes with lots of problems (such as, being very complex and bloated, and potentially incompatible with Win32 API).
Gonzo
Posts: 722
Joined: Dec 11, 2005 22:46

Re: Inline functions

Post by Gonzo »

dkl wrote:Personally I'm not interested in adding exceptions to FB. FB is native code, the only way to add exceptions would be to do it exactly like GCC does for C++ (DWARF and/or setjump/longjump), and that comes with lots of problems (such as, being very complex and bloated, and potentially incompatible with Win32 API).
I always thought it was simple, but I guess it's not.. :P (Just one more of those, it's so simple to use, it must be easy to implement..)
It's very handy to use them just for setup, and for ending the program with an error, with a specialized catch clause at the end
It's really the automatic unwinding of the stack that is valueable..
angros47
Posts: 2321
Joined: Jun 21, 2005 19:04

Re: Inline functions

Post by angros47 »

If the C emitter is used, shouldn't GCC optimize the code, inlining the functions by default?
marcov
Posts: 3455
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Inline functions

Post by marcov »

Gonzo wrote:
gothon wrote:However in C inline functions are often defined in headers inside their declaration so that the compiler doesn't generate an external symbol, so inlining after compiling is probably not often done.
I don't think you can do that, because inline functions need to be exposed to the code that uses it.
Nobody says that the inlined function must be visible in source form from where it is used. It only must be compiled before that use. This requires a link from the compiler to build order, and most C and GCC compilers are a bit old fashioned in this matter (probable because of the huge installed base on make-like systems). This is probably also why the inline is optional. If the original file is not compiled yet, it is not inlined, and you must manually fix/optimize your makefile.

I hope that Bjarne Stroustrup is really thinking about more modular aspects of C++ as he said in the interview after the last standard:-)

So if the inlined implementation is in the .C and not in the .H, any C that uses the inline function must be compiled after the corresponding .C, and while compiling that .C the implementation should be kept somewhere (tokenized or tree/IL form)

The non-inlined symbol is usually generated anyway, in case modules are compiled without inlining switch, and can be ejected by smartlinking (dead code elemination) if not.
Also are you guys thinking about using a more robust error/throw-catch system like there is in Java, .NET and C++?
There is good support for debugging this, in gcc "catch throw"
And make it SEH compatible from the start. Believe me :)
I'm not a big fan of throwing from constructors, since it sometimes bites you in the ass when you create objects passed directly to functions since you cannot regain the lost memory
That requires an object model where memory allocation and actual constructor are separated, a two step constructor so to say, where the first step allocates memory and calls the second step under a try catch. If it catches the exception, it frees the memory, reraises the exception and returns NULL. A static object directly calls the second level (actual) constructor.

Note that this only provides memory safety, not truly atomic constructors/destructors.
Post Reply