Thread overview
Second class pointers
Jul 08, 2016
Nicholas Wilson
Jul 08, 2016
Nicholas Wilson
Jul 08, 2016
ZombineDev
Jul 08, 2016
Nicholas Wilson
July 08, 2016
So as part of my effort to get D running on GPUs I need to make a "second class" pointer type that I can alter in the backend of LDC to the correct address space. to that end I have made the following

module dcompute.types.pointer;

enum Private = 0;
enum Global = 1;
enum Shared = 2;
enum Constant = 3;
enum Generic = 4;

pure @trusted nothrow @nogc
struct Pointer(uint p, T) if(p <= Generic)
{
    T* ptr;
    ref T opUnary(string op)() if(op=="*")
    {
        return *ptr;
    }
    ref T opIndex(size_t i)
    {
        return *(ptr+i);
    }
    auto opBinary(string op)(ptrdiff_t i) if(op=="+" || op == "-")
    {
         return Pointer!(p, T) (ptr + i);
    }
}

is there anything else that I'm missing that you can do with a raw pointer?

July 08, 2016
On Friday, 8 July 2016 at 05:53:21 UTC, Nicholas Wilson wrote:
> So as part of my effort to get D running on GPUs I need to make a "second class" pointer type that I can alter in the backend of LDC to the correct address space. to that end I have made the following
>
> module dcompute.types.pointer;
>
> enum Private = 0;
> enum Global = 1;
> enum Shared = 2;
> enum Constant = 3;
> enum Generic = 4;
>
> pure @trusted nothrow @nogc
> struct Pointer(uint p, T) if(p <= Generic)
> {
>     T* ptr;
>     ref T opUnary(string op)() if(op=="*")
>     {
>         return *ptr;
>     }
>     ref T opIndex(size_t i)
>     {
>         return *(ptr+i);
>     }
>     auto opBinary(string op)(ptrdiff_t i) if(op=="+" || op == "-")
>     {
>          return Pointer!(p, T) (ptr + i);
>     }
> }
>
> is there anything else that I'm missing that you can do with a raw pointer?

That should be mixin("ptr"~op~"i")
I need compound add and compound subtract as well.
July 08, 2016
On Friday, 8 July 2016 at 06:17:43 UTC, Nicholas Wilson wrote:
> On Friday, 8 July 2016 at 05:53:21 UTC, Nicholas Wilson wrote:
>> So as part of my effort to get D running on GPUs I need to make a "second class" pointer type that I can alter in the backend of LDC to the correct address space. to that end I have made the following
>>
>> module dcompute.types.pointer;
>>
>> enum Private = 0;
>> enum Global = 1;
>> enum Shared = 2;
>> enum Constant = 3;
>> enum Generic = 4;
>>
>> pure @trusted nothrow @nogc
>> struct Pointer(uint p, T) if(p <= Generic)
>> {
>>     T* ptr;
>>     ref T opUnary(string op)() if(op=="*")
>>     {
>>         return *ptr;
>>     }
>>     ref T opIndex(size_t i)
>>     {
>>         return *(ptr+i);
>>     }
>>     auto opBinary(string op)(ptrdiff_t i) if(op=="+" || op == "-")
>>     {
>>          return Pointer!(p, T) (ptr + i);
>>     }
>> }
>>
>> ...
>
> That should be mixin("ptr"~op~"i")
> I need compound add and compound subtract as well.

Why not make the address (memory) space a strongly-typed enum, e.g.:

enum AddressSpace
{
    threadLocal = 0,
    groupLocal = 1,
    global = 2,
    constant = 3,
    texture = 4
    generic = 5
}

struct Pointer(T, AddressSpace type = AddressSpace.Generic)
// ...

?

>> is there anything else that I'm missing that you can do with a raw pointer?

Slicing:

// Pseudo OpenCL-D

groupLocal T* ptr1;
groupLocal T[] slice1 = ptr1[2 .. 10];

global T* ptr2;
groupLocal T[] slice2 = ptr2[0 .. 2]; // Error
July 08, 2016
On Friday, 8 July 2016 at 11:05:36 UTC, ZombineDev wrote:
> On Friday, 8 July 2016 at 06:17:43 UTC, Nicholas Wilson wrote:
>> On Friday, 8 July 2016 at 05:53:21 UTC, Nicholas Wilson wrote:
>>> So as part of my effort to get D running on GPUs I need to make a "second class" pointer type that I can alter in the backend of LDC to the correct address space. to that end I have made the following
>>>
>>> module dcompute.types.pointer;
>>>
>>> enum Private = 0;
>>> enum Global = 1;
>>> enum Shared = 2;
>>> enum Constant = 3;
>>> enum Generic = 4;
>>>
>>> pure @trusted nothrow @nogc
>>> struct Pointer(uint p, T) if(p <= Generic)
>>> {
>>>     T* ptr;
>>>     ref T opUnary(string op)() if(op=="*")
>>>     {
>>>         return *ptr;
>>>     }
>>>     ref T opIndex(size_t i)
>>>     {
>>>         return *(ptr+i);
>>>     }
>>>     auto opBinary(string op)(ptrdiff_t i) if(op=="+" || op == "-")
>>>     {
>>>          return Pointer!(p, T) (ptr + i);
>>>     }
>>> }
>>>
>>> ...
>>
>> That should be mixin("ptr"~op~"i")
>> I need compound add and compound subtract as well.
>
> Why not make the address (memory) space a strongly-typed enum, e.g.:
>
> enum AddressSpace
> {
>     threadLocal = 0,
>     groupLocal = 1,
>     global = 2,
>     constant = 3,
>     texture = 4
>     generic = 5
> }
>
because it'll change the mangling and I just want to get it working first, also there will be aliases for all the things anyway. (also AFAIU there is no texture address space its just fancy caching)

> struct Pointer(T, AddressSpace type = AddressSpace.Generic)
> // ...
>
> ?
>
>>> is there anything else that I'm missing that you can do with a raw pointer?
>
> Slicing:
>
That's creating a new variable based on the pointer as {$-offset, ptr + offset} not a primitive, but I take your point.

> // Pseudo OpenCL-D
>
> groupLocal T* ptr1;
> groupLocal T[] slice1 = ptr1[2 .. 10];
>
> global T* ptr2;
> groupLocal T[] slice2 = ptr2[0 .. 2]; // Error

I REALLY want to avoid having to make them qualifiers and that means I have to hack DMDFE as well as LDC.