
@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.