Hello, I've defined a simple template used in a double linked list implementation:

template tDLListItem(T)
{
        const cPrevOffs = size_t.sizeof;
        const cNextOffs = size_t.sizeof + size_t.sizeof;
        void* NewItemCaps(T* aData, void* aPrevious, void* aNext)
        {
                auto lPt = std.c.stdlib.malloc( 3 * size_t.sizeof );
                if (!lPt)
                {
                        throw new OutOfMemoryError();
                }
                *cast(size_t*)  lPt = cast(size_t) aData;
                *cast(size_t*) (lPt + cPrevOffs) = cast(size_t) aPrevious;
                *cast(size_t*) (lPt + cNextOffs) = cast(size_t) aNext;
                return lPt;
        }
        void DeleteItemCaps(void* aItemCaps)
        {
                std.c.stdlib.free(aItemCaps);
        }
        void SetItemCapsPrev(void* aItemCaps, void* aPrevious)
        {
                *cast(size_t*) (aItemCaps + cPrevOffs) = cast(size_t) aPrevious;
        }
        void SetItemCapsNext(void* aItemCaps, void* aNext)
        {
                *cast(size_t*) (aItemCaps + cNextOffs) = cast(size_t) aNext;
        }
        void SetItemCapsData(void* aItemCaps, T* aData)
        {
                *cast(size_t*) aItemCaps = cast(size_t) aData;
        }
        T* GetItemCapsData(void* aItemCaps)
        {
                version(X86) asm
                {
                        naked;
                        mov     EAX, [EAX];
                        ret;
                }
                else version(none) asm
                {
                        naked;
                        mov     RAX, [RAX];
                        ret;
                }
                else
                {
                        return *cast(T**) (aItemCaps);
                }
        }
        void* PreviousItemCaps(void* aItemCaps)
        {
                version(X86) asm
                {
                        naked;
                        mov     EAX, [EAX + cPrevOffs];
                        ret;
                }
                else version(none) asm
                {
                        naked;
                        mov     RAX, [RAX + cPrevOffs];
                        ret;
                }
                else
                {
                        return *cast(size_t**) (aItemCaps + cPrevOffs);
                }
        }
        void* NextItemCaps(void* aItemCaps)
        {
                version(X86) asm
                {
                        naked;
                        mov     EAX, [EAX + cNextOffs];
                        ret;
                }
                else version(none) asm
                {
                        naked;
                        mov     RAX, [RAX + cNextOffs];
                        ret;
                }
                else
                {
                        return *cast(size_t**) (aItemCaps + cNextOffs);
                }
        }
}

It's used as a struct. (BTW I call the "payload" a "capsule", a "caps"). In x86 (tested on win) I can optimize the access into the "capsule" to a simple member (I return the data pointed by the parameter by digging using the param + memberoffset as an address...

But it doesn't work in x86_64 (tested on nux). What's wrong with that ? Does I miss something in the parameters convention/ABI for x64 (that's why the x64 versions are surounded by version(none) instead of version (X86_64) )) ?

Does dmd produce real x86_64 code or is it possible for a 64 bit appli to work with 32 bit pointers ? (I know this Q coulds look weird but I've already seen some false x86_64 while doing some static analysis)

WTF.MEH.

Reply via email to