sf.net bug https://sourceforge.net/p/fbc/bugs/881/
Working on a replacement though, it's not quite ready to merge in to master:
github https://github.com/freebasic/fbc/pull/115
In the update, to work with variadic functions and argument lists, here's what we've come up with:
cva_list is added as a default type by fbc to expose the argument list. It works kind of like an object, in that usually we don't need to know what's doing, only how to use it. There are a few methods in it's API for accessing a variable length list of arguments passed in to a procedure..
Code: Select all
dim args as cva_list = any
cva_start( args, param ) '' constructor
cva_copy( dest, args ) '' copy constructor
cva_end( args ) '' destructor
result = cva_arg( args, datatype ) '' method returns data and advances to next argument
- cva_start() needs exactly one matching cva_end()
- cva_copy() needs exactly one matching cva_end()
If it looks familiar, it is because it's just about the same in C. We could have come up with our own api, but then it wouldn't be compatible (link-able) with anything but our own code.
If you are currently using any of the new names being added: cva_list, cva_start, cva_end, cva_copy, cva_arg and depending on target __va_list_tag, __va_list, you will need to use #undef to get it out of your way, or rename the symbol in your code.
- No documentation written yet. This post is the first info.
- No guarantees that it is bug free. Please submit bug reports.
- Need help testing on ARM targets. (Or I have to create a VM for it)
Examples:
Iterate through a list of arguments
Code: Select all
sub proc cdecl( n as integer, ... )
dim args as cva_list
cva_start( args, n )
for i as integer = 1 to n
print "arg " & i & " = " & cva_arg( args, integer )
next i
cva_end( args )
end sub
proc( 3, 11, 22, 33 )
Code: Select all
sub proc2 cdecl( n as integer, byval args as cva_list )
dim x as cva_list = any
cva_copy( x, args )
for i as integer = 1 to n
print "arg " & i & " = " & cva_arg( x, integer )
next i
cva_end( x )
end sub
sub proc1 cdecl( n as integer, ... )
dim x as cva_list = any
cva_start( x, n )
proc2( n, x )
cva_end( x )
end sub
proc1( 3, 11, 22, 33 )
Internal stuff:
The implementation and code emitted for cva_list, cva_start, cva_copy, cva_end, cva_arg varies depending on target, backend, and architecture.
In -gen gas backend, these macros translate to expressions because we are providing our own implementation. With the cva_* macros being similar to the implementation of the fbc's existing va_* macros but having different behaviours.
In -gen gcc backend, the cva_* macros will map to gcc's builtin macros:
cva_list => __builtin_va_list
cva_start => __builtin_va_start
cva_arg => __builtin_va_arg
cva_end => __builtin_va_end
cva_copy => __builtin_va_copy
The cva_list data type is a hairy one, because it's type varies depending on the target:
Code: Select all
'' dos/win/linux x86 - gas backend
type cva_list as any alias "char" ptr
'' dos/win/linux/arm x86 - gcc backend
type cva_list as any alias "__builtin_va_list" ptr
'' win32 x86_64 - gcc backend
type cva_list as any alias "__builtin_va_list" ptr
'' linux x86_64 - gcc backend
type __va_list_tag alias "__va_list_tag"
as ulong gp_offset
as ulong fp_offset
as any ptr overflow_arg_area
as any ptr reg_save_area
end type
type cva_list as __va_list_tag alias "__builtin_va_list"
'' arm64/aarch64 - gcc backend
type __va_list alias "__va_list"
as any ptr __stack
as any ptr __gr_top
as any ptr __vr_top
as long __gr_offs
as long __vr_offs
end type
type cva_list as __va_list alias "__builtin_va_list"
Also, you should notice some new syntax with the AS datatype ALIAS "modifier". This is valid syntax. A side note here: a while ago added the following syntax: byval as long alias "long". This was specifically added to allow fbc programs to link with win32's 32 bit long int in gcc c++, which was previously impossible without this type modifier
What the ALIAS "modifier" allows, is using a datatype as you would expect in fbc, but then, in the backend emitter, do something special with it; mostly used for name mangling and linking. fbc has to do some other tricky stuff to be compatible across multiple targets because __builtin_va_list is typed differently on various targets.
The documenation for usage of ALIAS "modifier" should get its own new page, maybe KeyPgAliasTypeModifier