Obtain pointer from static array literal

Nicholas Wilson iamthewilsonator at hotmail.com
Fri Oct 8 05:01:00 UTC 2021


On Friday, 8 October 2021 at 02:49:17 UTC, codic wrote:
> I am working with a C API (XCB) which uses `void*` a lot to 
> obtain parameter packs; these are very small and throwaway so I 
> want them to be allocated to the stack.

CUDA has something similar that I have to deal with for 
dcompute[1]. The trick is that the parameter packs always have 
some sort of underlying structure to them and in D it is possible 
to exploit that structure at compile time to ensure that you 
don't break type safety. I can't give a more specific answer 
without some more concrete examples from XCB, but for CUDA the 
function signature of the kernel you are trying to launch 
dictates what goes into the parameter pack.

The best way is to generate (or write) wrapper functions that do 
this for you such that you can call `wrappedFunc(x,y,w,h)` and 
statically verify through its type signature that

> uint[4] params=[x,y,width,height];
> func(params.ptr);

is a valid call to func.

> Of course, this is valid, but a bit painful:
> ```d
> uint[4] params=[x,y,width,height];
> func(params.ptr);
> ```
> especially when you have lots of calls. now, this compiles:
> ```d
> // (import std.array)
> func([x,y,width,height].staticArray.ptr);
> ```
> but is it well-formed? or is it UB because it is a rvalue and 
> scope ends?

For simple types (i.e. ones with no destructor), like int, IIRC 
this is fine.
When you have a static array of objects that need to be 
destructed, then end of scope becomes important.

> i.e. here is an example program, is it well formed?
> ```d
> import core.stdc.stdio, std.array;
>
> void thing(int* abc) {
>   printf("%d\n", *abc);
> }
>
> extern(C) void main() {
>   thing([1].staticArray.ptr);
> }
> ```
> At any rate, it runs fine consistently with ldc:
> ```
> $ ldc2 test.d -fsanitize=address
> $ ./test
> 1
> ```
>
> I don't know if it is spec-compliant though, or if it is 
> actually causing UB here and I don't notice it.

note that if the pointer is not escaped from the function (i.e. 
`thing` is `void thing(scope int* abc)`note the addition of 
`scope`) LDC will perform promotion of GC allocation to stack of 
the array literal even if you don't use `.staticArray`.

https://github.com/libmir/dcompute/blob/master/source/dcompute/driver/cuda/queue.d#L80-L92


More information about the Digitalmars-d-learn mailing list