@kirisky has joined the channel
@mflatt So for what its worth, treeting the va_list like a pointer seems to cause erratic behavior.
I mean, the bug could be somewhere else, and I’m seeing if I can reduce it down.
But…a.
ya*
@leif What platform are you on?
Nevermind – I see that sizeof(va_list) is 24 bytes on Mac OS, so it must vary more than I thought, and I must have mangled my experiment before
Thinking about it more, a portable solution seems hopeless without va_list support in libffi, because the specific representation of a va_list can affect the way that it’s passed in registers or on the stack. The only idea I have is to define _va_list in ffi/unsafe based on the result of (system-library-subpath #f) – so it would work only for platforms where we’ve specifically tracked down and hard-coded the representation.
@mflatt ya, that sounds about right.
Also I’m on OS X.
I’ll look at the system V ABI specs, if they are at least consistent among different instruction sets we probably do have a chance
Looking at the c99 spec, it requires that va_list be a type.
And if that is the case, it seems like if we make a _va-list type, while we won’t be able to do anything with it in Racket code, it could be passed to C code.
(I’m looking at section 7.15 of the latest draft of the c99 spec.)
(As I don’t have a copy of the actual release.)
@leif Supporting va_list seems painful. Just found the section “Variable Length Arguments” in the SWIG manual. It has the subtitle “The horror. The horror.”
@soegaard2 Not trying support varargs…That would be really hard. :confused:
Just va_list.
Which is doable, as its just another value.
As long as it stays an opaque value to Racket, that is fine.
Trying to mimick va_arg, va_first, etc. or the ... protocol, that sounds scary.
At least based on what I’ve ascertained at the moment.
Iam clearly conflating those. Aren’t va_list used to deal with variable arguments?
You are correct.
va_list however, can also be passed to another function as a type.
This is used if you, say, want to make a helper function.
Ok. So va_list is also useful in other situations.
int myfunc(const char *str, ...) {
va_list ag;
va_start(ag);
helper(ag);
va_end(ag);
}
int helper(va_list ag) {
...
va_arg(ag);
...
}Yup
in this case, I want to write helper
In particular…
I want to write helper that just passes the va_list to another (C) function.
Because I’m hooking up two libraries.
Through Racket….
Of course, this still isn’t enough to duplicate va_copy, as that’s macro. To do that, we would need to make scheme_va_copy, or something like that.
Which does nothing but call the macro.
Of course, if we do that, it would make sense to do that for va_arg as well.
We couldn’t do va_start and va_end though, because that would require supporting vaargs, and ..., which, as you rightly pointed out, is terrifying.
At least, what it looks like anyway. Perhaps I’m wrong.
Thanks for the example.
Any time. :slightly_smiling_face:
@mflatt worksp/librktio/… vs librktio/… these two directories seem pretty similar. Is one of them deprecated?
There should be a “rktio” directory with the rktio implementation and a “worksp/librktio” directory with MSVC projects
I’m not seeing multiple “librktio” directories
err…ya, I mean worksp/rktio. That makes sense that one is for windows. Thanks.
@mflatt oh wait, no
I do see a worksp/librktio.
racket/racket/src/worksp/librktio
Just to be sure: there should only be one “rktio” and one “librktio” directory; the “librktio” directory should be in “worksp”, and the “rktio” directory should not be in “worksp”
Although that one does look like a visual studio project.
Ah, okay.
That is correct.
So, since windows has src/worksp/libffi, does that mean it doesn’t use src/foreign?
OH….
src/worksp/libffi probably is in pace of src/foreign/libffi.
The foreign.c part of src/foreign is included directly in libracket, while src/worksp/libffi is the project for src/foreign/libffi
Okay
Also, I realized, adding a primitive for va_list is silly, since per the spec, its just an (undefined) struct type.
So it would make a lot more sense to just add a function to the core that calls sizeof (which I suspect already exists), and then define _va-list in racket.
@leif Is even sizeof(va_list) useful, since the calling convention can depend on more than the size? For example, long and double are often passed differently – though I’ll grant that va_list is unlikely to be represented as a double. I still think it’s best to use (system-library-subpath #f) and hardwire a representation in ffi/unsafe for various known results.
Ah, fair.
@mflatt Actually, no. Since va_list is NOT a primitive in C (per the spec), it’ll be handled just like any other struct will.
(Like, the size and field order of the struct is undefined, but the fact that it is a struct is.)
“The type declared is va_list which is an object type suitable for holding information needed by the macros va_start, va_arg, va_end, and va_copy”
“object type” => “struct”?
Even so, I thought the way a struct is passed could depend on its content beyond just its size, but I forget these details
That is how I interpret it. Although I admit I didn’t make the spec so I’m not 100% sure.
Ok. FWIW, I don’t think “object” means “struct” in the C standard
Also ya, it certainly is true that structs are passed differently based on what is in them.
Hmm…okay.
I’ll see if I can find an answer to that. Thanks. :slightly_smiling_face:
@mflatt “object: region of data storage in the execution environment, the contents of which can represent values”
So I guess it could be a primitive.
Just not a macro.