Embedded function calls

New to FreeBASIC? Post your questions here.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: Embedded function calls

Post by caseih »

Flyzone wrote:
apparently Quick Basic had no issue with forward referencing a function without any sort of advanced declaration. FB does not allow that, nor can I think of a good reason to allow that.
You can't? You just mentioned two of them. There are others ...
No I didn't. I can see that we have a terminology problem here and that you're not understanding what I wrote, which is a bit surprising given your extensive background in older languages. I did not say I couldn't think of a reason to have forward references. Forward references are generally required for all but the simplest of programs. I said there's no reason for FB to support forward references without first declaring a function prototype.
Never programmed in C; never will. You are obviously much younger and the 6 or so languages I have programmed in predate you but the technology has changed considerably and after many years of non-participation I am toying with FB keeping one foot in the past on placing another in today's tech. I hope they don't try to make FB a C lookalike-workalike. I actually heard John Kemeny (originator of Basic) speak and he'd be horrified. However, I like what they've done with FB so far.
A bit of an odd statement given that C is nearly 50 years old (astounding to realize, really). But yes, on the mainframe other languages dominated for years before that. I'd love to hear from you the languages you used before so maybe we can identify some common frames of reference.

As to what BASIC has become, Niklaus Wirth would very much approve of BASIC becoming more formal and structured. Yes FB has turned out nicely. The ability to interoperate with libraries written in C, and to make FB capable of emulating C calling conventions and C data types and structures, makes FB very powerful on modern operating systems.
Thanks for the info on libs. I'll try them out even though a source include would be easiest but I'd like to recreate what we used to call relocatable modules/libraries just to see how same/different they might be. Some things haven't changed at all.
DLLs are shared libraries and are by definition "relocatable." FB can create DLLs (which can be used by any other language also). See the wiki pages for more information on make and using shared libraries with FB. See https://www.freebasic.net/wiki/ProPgSharedLibraries, or more generally, https://www.freebasic.net/wiki/CatPgProgrammer

The header/implementation paradigm is not just limited to DLLs. You can use it to good effect within a single program. For example you could have one .bas file that defines a number of utility functions you use throughout your program. A .bi file gives the sub and function prototypes and any user-defined types associated with that utility .bas file. Then in each of your .bas modules you can include the .bi file and use those functions. When linking the final executable, just link in all the .o files from the individual .bas files. Seems like most FB programmers are unaware of this style of code organization and modularization, which is a pity because it can dramatically decrease compile times. This is equivalent to what you call "source include."
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Embedded function calls

Post by dodicat »

Regarding dll's.
What I have not achieved so far is to pass gcc optimisations (-O2 or -O3) to a .dll file.
fbc somefile .bas -dll -Wc -O3
and
fbc somefile .bas -dll
produce slightly different somefile.dll, but the execution speeds for exported functions are the same for each.

I have also tested this with files written in c and made into dlls, with and without optimisations, again no speed difference when using them with fb.
I have also tested with fb static libs, again no speed difference.

Any ideas?
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Embedded function calls

Post by coderJeff »

dodicat wrote:I have also tested this with files written in c and made into dlls, with and without optimisations, again no speed difference when using them with fb.
I have also tested with fb static libs, again no speed difference.

Any ideas?
If the fb source is all in one module then gcc can optimize functions inline where they are used; optimizing out call/ret, copying values to registers, etc. With all the code in one module there are more opportunities for gcc to optimize fbc's emitted C code.

When the code is separated by modules, like an object file, static library, or shared library (dll), then generally the call to procedure and passing arguments need to remain as-is.

I don't know much about it, but for static libraries looks like link-time-optimization (LTO) could be used. Looks like requires compiling the C files with the gcc '-flto' option. https://gcc.gnu.org/wiki/LinkTimeOptimization
When I tried briefly on my mingw-w64 set-up, the linker (LD) complains that a plug-in is missing, so obviously have to install something else (if it exists) to make this work.

I suspect won't be able to get inter (intra?) procedures optimizations with shared libraries because the code in the library isn't loaded / linked until run-time.
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Embedded function calls

Post by coderJeff »

Flyzone wrote:even though a source include would be easiest but I'd like to recreate what we used to call relocatable modules/libraries just to see how same/different they might be.
This is rather vague as to what you are talking about. From one perspective, object files (in static libraries) are relocatable until they are linked. And even then, an executable when loaded can have different sections of code and data located to different parts of memory only known at run time.
Flyzone
Posts: 109
Joined: Nov 17, 2017 17:39

Re: Embedded function calls

Post by Flyzone »

I said there's no reason for FB to support forward references without first declaring a function prototype.
That's exactly what I was referring to. FB should permit forward references and should not require a pre-declaration (i.e. let the compiler do it.) JMHO. If you don't get it now, just hit escape ...
A bit of an odd statement given that C is nearly 50 years old (astounding to realize, really).
Kind of snide actually. I'm not denigrating anyone who wants to program in C or the language itself - just that I have no interest and won't be. My past: PL/1, ALC/BAL, APL, RPG, Cobol, SPS/Autocoder, applications and systems programming, GW-Basic for utility programming, Algol but never proficient, some 6809 programming, others (Mark IV ...)
This is rather vague as to what you are talking about. From one perspective, object files (in static libraries) are relocatable until they are linked. And even then, an executable when loaded can have different sections of code and data located to different parts of memory only known at run time.
No kidding ...
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Embedded function calls

Post by marcov »

coderJeff wrote:
dodicat wrote:I have also tested this with files written in c and made into dlls, with and without optimisations, again no speed difference when using them with fb.
I have also tested with fb static libs, again no speed difference.

Any ideas?
If the fb source is all in one module then gcc can optimize functions inline where they are used; optimizing out call/ret, copying values to registers, etc. With all the code in one module there are more opportunities for gcc to optimize fbc's emitted C code.
FB could lift functions from the .bas to the .bi to make them inlineable. Not every gcc limitation is an unsurmountable wall. And if gcc was the problem, then GAS backend could ? :-)

When the code is separated by modules, like an object file, static library, or shared library (dll), then generally the call to procedure and passing arguments need to remain as-is.
If the code is final, yes.
I don't know much about it, but for static libraries looks like link-time-optimization (LTO) could be used. Looks like requires compiling the C files with the gcc '-flto' option. https://gcc.gnu.org/wiki/LinkTimeOptimization
When I tried briefly on my mingw-w64 set-up, the linker (LD) complains that a plug-in is missing, so obviously have to install something else (if it exists) to make this work.
In any solution, you need to keep a tree representation of the code for inlining. This is not just important for cross-module inlining, but also for generics, which can't be written out into final compiled code.
I suspect won't be able to get inter (intra?) procedures optimizations with shared libraries because the code in the library isn't loaded / linked until run-time.
Depends. Nearly always when you inline a module, the non-inlined symbol is kept in case there are other modules that don't inline (e.g. an auto inliner could decide inlining in a certain place is not worth it). So the fact that there is a final linkable version of the module is not the problem, that is normal.

What you lack is a representation in some intermediate form that you can inline, on top of that. That's what LTO afaik tries to do.

But I think this hits the limit of what you can do with a source only backend. If you really want this and you don't want to do it yourself, better go the LLVM way.
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Embedded function calls

Post by dodicat »

Believe it or not.
fb dll's carry the optimisations if used by c++
for those who are interested
isprime.bas (simply dll)

Code: Select all

 Function isaprime(n As ulongint) As long export
    If (n=2) Or (n=3) Then Return -1
    If n Mod 2 = 0 Then return 0
    If n Mod 3 = 0 Then return 0
    Dim As ulongint limit=Sqr(N)+1
    For I As ulongint = 6 To limit Step 6
        If N Mod (i-1) = 0 Then return 0
        If N Mod (i+1) = 0 Then return 0
    Next I
    Return -1
End Function

'compile fbc -dll -export 
and, the same thing
isprimeopt.bas (dll optimised O3)

Code: Select all

 Function isaprime(n As ulongint) As long export
    If (n=2) Or (n=3) Then Return -1
    If n Mod 2 = 0 Then return 0
    If n Mod 3 = 0 Then return 0
    Dim As ulongint limit=Sqr(N)+1
    For I As ulongint = 6 To limit Step 6
        If N Mod (i-1) = 0 Then return 0
        If N Mod (i+1) = 0 Then return 0
    Next I
    Return -1
End Function


'compile fbc -dll -Wc -O3 -export 
and the test c++ code

Code: Select all

#include <windows.h>
#include<stdio.h>
#include<iostream>
using namespace std;
typedef int ( * theisprime)(unsigned long long);

theisprime isprime;


HINSTANCE LB ;
void init()
{
LB = LoadLibrary(TEXT("isprimeopt.dll")); // test each one by commenting out the other
//LB = LoadLibrary(TEXT("isprime.dll"));
if (LB==0)
{
printf("Dll not found\n");
system("pause");
exit(EXIT_SUCCESS);
}
//isprime = (theisprime) GetProcAddress(LB, "isprime");
isprime = (theisprime) GetProcAddress(LB, "ISAPRIME");
if(isprime == 0) cout<<" function isprime not loaded"<<endl;
if(isprime != 0) cout<<" function isprime loaded  Please wait . . ."<<endl;
}
int main()
{
	init();
	cout<<isprime(18446744073709551557ull)<<endl;
}  
I tested dev cpp 64 bit release
optimised dll about 10 seconds
unoptimised dll about 14 seconds
All files in the same test folder of course.
You can delete the freeBASIC import libs (dll.a), they are not needed
NOTE:
gcc 8.1 and gcc 8.4 fail to create an optimised dll, I get a pile of warnings and the dll fails.
(I have only tested 8.1 and 8.4)
FreeBASIC-1.07.2-win64\fbc.exe official build is good with gcc 5.2
deltarho[1859]
Posts: 4305
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: Embedded function calls

Post by deltarho[1859] »

32-bit & 64-bit 1.07.1

5.2 warning .drectve -> No
6.4 warning .drectve -> No
7.4 warning .drectve -> Yes
7.5 warning .drectve -> Yes
8.3 warning .drectve -> Yes
8.4 warning .drectve -> Yes
9.2 warning .drectve -> Yes
9.3 warning .drectve -> Yes

Issue may well have started with gcc 7.0 and is clearly not a 8.x issue only.

fbc needs to check the gcc version and act accordingly; although a 'fix' may not upset gcc 5 or 6.
Post Reply