Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #2038: tango-dmd64.patch

File tango-dmd64.patch, 27.2 kB (added by Marenz, 13 years ago)

more work on 64bit dmd

  • object.di

    old new  
    131131    PointerMap pointermap(); 
    132132    /// offsets of the various elements 
    133133    OffsetTypeInfo[] offTi(); 
     134 
     135    /** Return internal info on arguments fitting into 8byte. 
     136       * See X86-64 ABI 3.2.3 
     137     */ 
     138    version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2); 
    134139} 
    135140 
    136141class TypeInfo_Typedef : TypeInfo 
  • tango/core/rt/gc/basic/gcx.d

    old new  
    23442344        } 
    23452345        else 
    23462346        { 
    2347         asm 
     2347        version (D_InlineAsm_X86) 
    23482348        { 
    2349             pushad              ; 
    2350             mov sp[EBP],ESP     ; 
     2349            asm 
     2350            { 
     2351                pushad              ; 
     2352                mov sp[EBP],ESP     ; 
     2353            } 
    23512354        } 
     2355        else version (D_InlineAsm_X86_64) 
     2356        { 
     2357            asm 
     2358            { 
     2359                push RAX ; 
     2360                push RBX ; 
     2361                push RCX ; 
     2362                push RDX ; 
     2363                push RSI ; 
     2364                push RDI ; 
     2365                push RBP ; 
     2366                push R8  ; 
     2367                push R9  ; 
     2368                push R10  ; 
     2369                push R11  ; 
     2370                push R12  ; 
     2371                push R13  ; 
     2372                push R14  ; 
     2373                push R15  ; 
     2374                push EAX ;   // 16 byte align the stack 
     2375            } 
    23522376        } 
     2377        else 
     2378        { 
     2379            static assert( false, "Architecture not supported." ); 
     2380        } 
     2381        } 
    23532382        result = fullcollect(sp); 
    23542383        version (GNU) 
    23552384        { 
     
    25192548        for (n = 0; n < npools; n++) 
    25202549        {   size_t pn; 
    25212550            size_t ncommitted; 
    2522             uint*  bbase; 
    25232551 
    25242552            pool = pooltable[n]; 
    2525             bbase = pool.mark.base(); 
     2553            auto bbase = pool.mark.base(); 
    25262554            ncommitted = pool.ncommitted; 
    25272555            for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) 
    25282556            { 
  • tango/core/rt/gc/basic/gcbits.d

    old new  
    5050 
    5151struct GCBits 
    5252{ 
    53     const int BITS_PER_WORD = 32; 
    54     const int BITS_SHIFT = 5; 
    55     const int BITS_MASK = 31; 
     53    alias size_t wordtype; 
    5654 
    57     uint*  data = null; 
     55    const BITS_PER_WORD = (wordtype.sizeof * 8); 
     56    const BITS_SHIFT = (wordtype.sizeof == 8 ? 6 : 5); 
     57    const BITS_MASK = (BITS_PER_WORD - 1); 
     58    const BITS_1 = cast(wordtype)1; 
     59 
     60    wordtype*  data = null; 
    5861    size_t nwords = 0;    // allocated words in data[] excluding sentinals 
    5962    size_t nbits = 0;     // number of bits in data[] excluding sentinals 
    6063 
     
    7982    { 
    8083        this.nbits = nbits; 
    8184        nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT; 
    82         data = cast(uint*)calloc(nwords + 2, uint.sizeof); 
     85        data = cast(wordtype*)calloc(nwords + 2, wordtype.sizeof); 
    8386        if (!data) 
    8487            onOutOfMemoryError(); 
    8588    } 
    8689 
    87     uint test(size_t i) 
     90    wordtype test(size_t i) 
    8891    in 
    8992    { 
    9093        assert(i < nbits); 
     
    9295    body 
    9396    { 
    9497        //return (cast(bit *)(data + 1))[i]; 
    95         return data[1 + (i >> BITS_SHIFT)] & (1 << (i & BITS_MASK)); 
     98        return data[1 + (i >> BITS_SHIFT)] & (BITS_1 << (i & BITS_MASK)); 
    9699    } 
    97100 
    98101    void set(size_t i) 
     
    103106    body 
    104107    { 
    105108        //(cast(bit *)(data + 1))[i] = 1; 
    106         data[1 + (i >> BITS_SHIFT)] |= (1 << (i & BITS_MASK)); 
     109        data[1 + (i >> BITS_SHIFT)] |= (BITS_1 << (i & BITS_MASK)); 
    107110    } 
    108111 
    109112    void clear(size_t i) 
     
    114117    body 
    115118    { 
    116119        //(cast(bit *)(data + 1))[i] = 0; 
    117         data[1 + (i >> BITS_SHIFT)] &= ~(1 << (i & BITS_MASK)); 
     120        data[1 + (i >> BITS_SHIFT)] &= ~(BITS_1 << (i & BITS_MASK)); 
    118121    } 
    119122 
    120     uint testClear(size_t i) 
     123    wordtype testClear(size_t i) 
    121124    { 
    122125        version (bitops) 
    123126        { 
     
    136139            } 
    137140        } 
    138141        else 
    139         {   uint result; 
     142        {   wordtype result; 
    140143 
    141144            //result = (cast(bit *)(data + 1))[i]; 
    142145            //(cast(bit *)(data + 1))[i] = 0; 
    143146 
    144             uint* p = &data[1 + (i >> BITS_SHIFT)]; 
    145             uint  mask = (1 << (i & BITS_MASK)); 
     147            wordtype* p = &data[1 + (i >> BITS_SHIFT)]; 
     148            wordtype  mask = (BITS_1 << (i & BITS_MASK)); 
    146149            result = *p & mask; 
    147150            *p &= ~mask; 
    148151            return result; 
     
    188191            for (;d1!=dEnd;++d1) 
    189192                *d1=0u; 
    190193        } else { 
    191             memset(data + 1, 0, nwords * uint.sizeof); 
     194            memset(data + 1, 0, nwords * wordtype.sizeof); 
    192195        } 
    193196    } 
    194197 
     
    200203    body 
    201204    { 
    202205        version(MEMCPY_NON_SIG_SAFE) { 
    203             uint * d1=data+1,d2=f.data+1,dEnd=d1+nwords; 
     206            wordtype * d1=data+1,d2=f.data+1,dEnd=d1+nwords; 
    204207            for (;d1!=dEnd;++d1,++d2) 
    205208                *d1=*d2; 
    206209        } else { 
    207             memcpy(data + 1, f.data + 1, nwords * uint.sizeof); 
     210            memcpy(data + 1, f.data + 1, nwords * wordtype.sizeof); 
    208211        } 
    209212    } 
    210213 
    211     uint* base() 
     214    wordtype* base() 
    212215    in 
    213216    { 
    214217        assert(data); 
  • tango/core/rt/compiler/dmd/rt/lifetime.d

    old new  
    303303    if (ndims == 0) 
    304304        result = 0; 
    305305    else 
    306     {   va_list q; 
    307         va_start!(int)(q, ndims)
     306    {    
     307        va_list q
    308308 
     309        version(X86) 
     310            va_start(q, ndims); 
     311        else version(X86_64) 
     312            va_start(q, __va_argsave); 
     313        else 
     314            static assert(false, "platform not supported"); 
     315 
    309316        void[] foo(TypeInfo ti, size_t* pdim, int ndims) 
    310317        { 
    311318            size_t dim = *pdim; 
     
    358365    else 
    359366    { 
    360367        va_list q; 
    361         va_start!(int)(q, ndims); 
    362368 
     369        version(X86) 
     370            va_start(q, ndims); 
     371        else version(X86_64) 
     372            va_start(q, __va_argsave); 
     373        else 
     374            static assert(false, "platform not supported"); 
     375 
    363376        void[] foo(TypeInfo ti, size_t* pdim, int ndims) 
    364377        { 
    365378            size_t dim = *pdim; 
     
    11671180        } 
    11681181        result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); 
    11691182 
    1170         va_list q; 
    1171         va_start!(size_t)(q, length); 
     1183        version(X86) 
     1184        { 
     1185            va_list q; 
     1186            va_start!(size_t)(q, length); 
    11721187 
    1173         size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); 
     1188            size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); 
    11741189 
    1175         if (stacksize == sizeelem) 
    1176         { 
    1177             memcpy(result, q, length * sizeelem); 
     1190            if (stacksize == sizeelem) 
     1191            { 
     1192                memcpy(result, q, length * sizeelem); 
     1193            } 
     1194            else 
     1195            { 
     1196                for (size_t i = 0; i < length; i++) 
     1197                { 
     1198                    memcpy(result + i * sizeelem, q, sizeelem); 
     1199                    q += stacksize; 
     1200                } 
     1201            } 
     1202 
     1203            va_end(q); 
    11781204        } 
    1179         else 
     1205        else version(X86_64) 
    11801206        { 
     1207            va_list q; 
     1208            va_start(q, __va_argsave); 
    11811209            for (size_t i = 0; i < length; i++) 
    11821210            { 
    1183                 memcpy(result + i * sizeelem, q, sizeelem); 
    1184                 q += stacksize; 
     1211                va_arg(q, ti.next, result + i * sizeelem); 
    11851212            } 
     1213            va_end(q); 
    11861214        } 
    1187  
    1188         va_end(q); 
    11891215    } 
    11901216    return result; 
    11911217} 
  • tango/core/rt/compiler/dmd/rt/aaA.d

    old new  
    110110 
    111111size_t aligntsize(size_t tsize) 
    112112{ 
    113     // Is pointer alignment on the x64 4 bytes or 8? 
    114     return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     113    version (X86_64) 
     114        // Size of key needed to align value on 16 bytes 
     115        return (tsize + 15) & ~(15); 
     116    else 
     117        return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
    115118} 
    116119 
    117120extern (C): 
     
    824827    else 
    825828    { 
    826829        va_list q; 
    827         va_start!(size_t)(q, length); 
     830        version(X86_64) va_start(q, __va_argsave); else va_start!(size_t)(q, length); 
    828831 
    829832        result = new BB(); 
    830833        result.keyti = keyti; 
  • tango/core/rt/compiler/dmd/object_.d

    old new  
    473473 
    474474    /// Get type information on the contents of the type; null if not available 
    475475    OffsetTypeInfo[] offTi() { return null; } 
     476 
     477 
     478     /** Return internal info on arguments fitting into 8byte. 
     479       * See X86-64 ABI 3.2.3 
     480     */ 
     481    version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) 
     482    {   arg1 = this; 
     483        return 0; 
     484    } 
    476485} 
    477486 
    478487class TypeInfo_Typedef : TypeInfo 
  • tango/core/Variant.d

    old new  
    3737            version=EnableVararg; 
    3838        } 
    3939    } 
     40    version( X86_64 ) 
     41    { 
     42        version( Windows ) 
     43        { 
     44            version=EnableVararg; 
     45        } 
     46        else version( Posix ) 
     47        { 
     48            version=EnableVararg; 
     49        } 
     50    } 
    4051} 
    4152else version( LDC ) 
    4253{ 
  • tango/core/Thread.d

    old new  
    348348            { 
    349349                __builtin_unwind_init(); 
    350350            } 
     351            else version ( D_InlineAsm_X86_64 ) 
     352            { 
     353                asm 
     354                { 
     355                    // Not sure what goes here, pushad is invalid in 64 bit code 
     356                    push RAX ; 
     357                    push RBX ; 
     358                    push RCX ; 
     359                    push RDX ; 
     360                    push RSI ; 
     361                    push RDI ; 
     362                    push RBP ; 
     363                    push R8  ; 
     364                    push R9  ; 
     365                    push R10 ; 
     366                    push R11 ; 
     367                    push R12 ; 
     368                    push R13 ; 
     369                    push R14 ; 
     370                    push R15 ; 
     371                    push EAX ;   // 16 byte align the stack 
     372                } 
     373            } 
    351374            else 
    352375            { 
    353376                static assert( false, "Architecture not supported." ); 
     
    411434            { 
    412435                // registers will be popped automatically 
    413436            } 
     437            else version ( D_InlineAsm_X86_64 ) 
     438            { 
     439                asm 
     440                { 
     441                    // Not sure what goes here, popad is invalid in 64 bit code 
     442                    pop EAX ;   // 16 byte align the stack 
     443                    pop R15 ; 
     444                    pop R14 ; 
     445                    pop R13 ; 
     446                    pop R12 ; 
     447                    pop R11 ; 
     448                    pop R10 ; 
     449                    pop R9  ; 
     450                    pop R8  ; 
     451                    pop RBP ; 
     452                    pop RDI ; 
     453                    pop RSI ; 
     454                    pop RDX ; 
     455                    pop RCX ; 
     456                    pop RBX ; 
     457                    pop RAX ; 
     458                } 
     459            } 
    414460            else 
    415461            { 
    416462                static assert( false, "Architecture not supported." ); 
     
    26702716        } 
    26712717        else version( AsmX86_64_Posix ) 
    26722718        { 
    2673             asm 
     2719            version( DigitalMars ) asm 
    26742720            { 
    26752721                naked; 
    26762722 
    26772723                // save current stack state 
     2724                push RBP; 
     2725                mov RBP, RSP; 
     2726                push RBX; 
     2727                push R12; 
     2728                push R13; 
     2729                push R14; 
     2730                push R15; 
     2731                sub RSP, 4; 
     2732                stmxcsr [RSP]; 
     2733                sub RSP, 4; 
     2734                //version(SynchroFloatExcept){ 
     2735                    fstcw [RSP]; 
     2736                    fwait; 
     2737                //} else { 
     2738                //    fnstcw [RSP]; 
     2739                //    fnclex; 
     2740                //} 
     2741 
     2742                // store oldp again with more accurate address 
     2743                mov [RDI], RSP; 
     2744                // load newp to begin context switch 
     2745                mov RSP, RSI; 
     2746 
     2747                // load saved state from new stack 
     2748                fldcw [RSP]; 
     2749                add RSP, 4; 
     2750                ldmxcsr [RSP]; 
     2751                add RSP, 4; 
     2752                pop R15; 
     2753                pop R14; 
     2754                pop R13; 
     2755                pop R12; 
     2756 
     2757                pop RBX; 
     2758                pop RBP; 
     2759 
     2760                // 'return' to complete switch 
     2761                ret; 
     2762 
     2763            } 
     2764            else asm 
     2765            { 
     2766                naked; 
     2767 
     2768                // save current stack state 
    26782769                pushq RBP; 
    26792770                mov RBP, RSP; 
    26802771                pushq RBX; 
  • tango/core/Vararg.d

    old new  
    2121} 
    2222else 
    2323{ 
    24     /** 
    25      * The base vararg list type. 
    26      */ 
     24version (X86) 
     25
    2726    alias void* va_list; 
    2827 
    29  
    30     /** 
    31      * This function initializes the supplied argument pointer for subsequent 
    32      * use by va_arg and va_end. 
    33      * 
    34      * Params: 
    35      *  ap      = The argument pointer to initialize. 
    36      *  paramn  = The identifier of the rightmost parameter in the function 
    37      *            parameter list. 
    38      */ 
    39     void va_start(T) ( out va_list ap, ref T parmn ) 
     28    template va_arg(T) 
    4029    { 
    41         ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 
     30        T va_arg(inout va_list _argptr) 
     31        { 
     32            T arg = *cast(T*)_argptr; 
     33            _argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)); 
     34            return arg; 
     35        } 
    4236    } 
     37} 
     38else 
     39{ 
     40    public import tango.stdc.stdarg; 
     41} 
    4342 
    44     /** 
    45      * This function returns the next argument in the sequence referenced by 
    46      * the supplied argument pointer.  The argument pointer will be adjusted 
    47      * to point to the next arggument in the sequence. 
    48      * 
    49      * Params: 
    50      *  ap  = The argument pointer. 
    51      * 
    52      * Returns: 
    53      *  The next argument in the sequence.  The result is undefined if ap 
    54      *  does not point to a valid argument. 
    55      */ 
    56     T va_arg(T) ( ref va_list ap ) 
    57     { 
    58         T arg = *cast(T*) ap; 
    59         ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 
    60         return arg; 
    61     } 
    62  
    63     /** 
    64      * This function cleans up any resources allocated by va_start.  It is 
    65      * currently a no-op and exists mostly for syntax compatibility with 
    66      * the variadric argument functions for C. 
    67      * 
    68      * Params: 
    69      *  ap  = The argument pointer. 
    70      */ 
    71     void va_end( va_list ap ) 
    72     { 
    73  
    74     } 
    75  
    76  
    77     /** 
    78      * This function copied the argument pointer src to dst. 
    79      * 
    80      * Params: 
    81      *  src = The source pointer. 
    82      *  dst = The destination pointer. 
    83      */ 
    84     void va_copy( out va_list dst, va_list src ) 
    85     { 
    86         dst = src; 
    87     } 
    8843} 
  • tango/stdc/stdarg.d

    old new  
    88 */ 
    99module tango.stdc.stdarg; 
    1010 
    11  
    1211version( GNU ) 
    1312{ 
    1413    public import std.c.stdarg; 
     
    1918} 
    2019else 
    2120{ 
     21version (X86) 
     22{ 
     23    /********************* 
     24     * The argument pointer type. 
     25     */ 
    2226    alias void* va_list; 
    2327 
    24     template va_start( T ) 
     28    /********** 
     29     * Initialize ap. 
     30     * For 32 bit code, parmn should be the last named parameter. 
     31     * For 64 bit code, parmn should be __va_argsave. 
     32     */ 
     33    void va_start(T)(out va_list ap, inout T parmn) 
    2534    { 
    26         void va_start( out va_list ap, ref T parmn ) 
     35        ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 
     36    } 
     37 
     38    /************ 
     39     * Retrieve and return the next value that is type T. 
     40     * Should use the other va_arg instead, as this won't work for 64 bit code. 
     41     */ 
     42    T va_arg(T)(inout va_list ap) 
     43    { 
     44        T arg = *cast(T*)ap; 
     45        ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 
     46        return arg; 
     47    } 
     48 
     49    /************ 
     50     * Retrieve and return the next value that is type T. 
     51     * This is the preferred version. 
     52     */ 
     53    void va_arg(T)(inout va_list ap, inout T parmn) 
     54    { 
     55        parmn = *cast(T*)ap; 
     56        ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 
     57    } 
     58 
     59    /************* 
     60     * Retrieve and store through parmn the next value that is of TypeInfo ti. 
     61     * Used when the static type is not known. 
     62     */ 
     63    void va_arg()(inout va_list ap, TypeInfo ti, void* parmn) 
     64    { 
     65        // Wait until everyone updates to get TypeInfo.talign() 
     66        //auto talign = ti.talign(); 
     67        //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); 
     68        auto p = ap; 
     69        auto tsize = ti.tsize(); 
     70        ap = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 
     71        parmn[0..tsize] = p[0..tsize]; 
     72    } 
     73 
     74    /*********************** 
     75     * End use of ap. 
     76     */ 
     77    void va_end(va_list ap) 
     78    { 
     79    } 
     80 
     81    void va_copy(out va_list dest, va_list src) 
     82    { 
     83        dest = src; 
     84    } 
     85
     86else version (X86_64) 
     87
     88    // Layout of this struct must match __gnuc_va_list for C ABI compatibility 
     89    struct __va_list 
     90    { 
     91        uint offset_regs = 6 * 8;            // no regs 
     92        uint offset_fpregs = 6 * 8 + 8 * 16; // no fp regs 
     93        void* stack_args; 
     94        void* reg_args; 
     95    } 
     96 
     97    struct __va_argsave_t 
     98    { 
     99        size_t[6] regs;   // RDI,RSI,RDX,RCX,R8,R9 
     100        real[8] fpregs;   // XMM0..XMM7 
     101        __va_list va; 
     102    } 
     103 
     104    /* 
     105     * Making it an array of 1 causes va_list to be passed as a pointer in 
     106     * function argument lists 
     107     */ 
     108    alias void* va_list; 
     109 
     110    void va_start(T)(out va_list ap, inout T parmn) 
     111    { 
     112        ap = &parmn.va; 
     113    } 
     114 
     115    T va_arg(T)(va_list ap) 
     116    {   T a; 
     117        va_arg(ap, a); 
     118        return a; 
     119    } 
     120 
     121    void va_arg(T)(va_list apx, inout T parmn) 
     122    { 
     123        __va_list* ap = cast(__va_list*)apx; 
     124        static if (is(T U == __argTypes)) 
    27125        { 
    28             ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 
     126            static if (U.length == 0 || T.sizeof > 16 || U[0].sizeof > 8) 
     127            {   // Always passed in memory 
     128                // The arg may have more strict alignment than the stack 
     129                auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); 
     130                ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 
     131                parmn = *cast(T*)p; 
     132            } 
     133            else static if (U.length == 1) 
     134            {   // Arg is passed in one register 
     135                alias U[0] T1; 
     136                static if (is(T1 == double) || is(T1 == float)) 
     137                {   // Passed in XMM register 
     138                    if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 
     139                    { 
     140                        parmn = *cast(T*)(ap.reg_args + ap.offset_fpregs); 
     141                        ap.offset_fpregs += 16; 
     142                    } 
     143                    else 
     144                    { 
     145                        parmn = *cast(T*)ap.stack_args; 
     146                        ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     147                    } 
     148                } 
     149                else 
     150                {   // Passed in regular register 
     151                    if (ap.offset_regs < 6 * 8 && T.sizeof <= 8) 
     152                    { 
     153                        parmn = *cast(T*)(ap.reg_args + ap.offset_regs); 
     154                        ap.offset_regs += 8; 
     155                    } 
     156                    else 
     157                    { 
     158                        auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); 
     159                        ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 
     160                        parmn = *cast(T*)p; 
     161                    } 
     162                } 
     163            } 
     164            else static if (U.length == 2) 
     165            {   // Arg is passed in two registers 
     166                alias U[0] T1; 
     167                alias U[1] T2; 
     168 
     169                static if (is(T1 == double) || is(T1 == float)) 
     170                { 
     171                    if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 
     172                    { 
     173                        *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_fpregs); 
     174                        ap.offset_fpregs += 16; 
     175                    } 
     176                    else 
     177                    { 
     178                        *cast(T1*)&parmn = *cast(T1*)ap.stack_args; 
     179                        ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     180                    } 
     181                } 
     182                else 
     183                { 
     184                    if (ap.offset_regs < 6 * 8 && T1.sizeof <= 8) 
     185                    { 
     186                        *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_regs); 
     187                        ap.offset_regs += 8; 
     188                    } 
     189                    else 
     190                    { 
     191                        *cast(T1*)&parmn = *cast(T1*)ap.stack_args; 
     192                        ap.stack_args += 8; 
     193                    } 
     194                } 
     195 
     196                auto p = cast(void*)&parmn + 8; 
     197                static if (is(T2 == double) || is(T2 == float)) 
     198                { 
     199                    if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 
     200                    { 
     201                        *cast(T2*)p = *cast(T2*)(ap.reg_args + ap.offset_fpregs); 
     202                        ap.offset_fpregs += 16; 
     203                    } 
     204                    else 
     205                    { 
     206                        *cast(T2*)p = *cast(T2*)ap.stack_args; 
     207                        ap.stack_args += (T2.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     208                    } 
     209                } 
     210                else 
     211                { 
     212                    void* a = void; 
     213                    if (ap.offset_regs < 6 * 8 && T2.sizeof <= 8) 
     214                    { 
     215                        a = ap.reg_args + ap.offset_regs; 
     216                        ap.offset_regs += 8; 
     217                    } 
     218                    else 
     219                    { 
     220                        a = ap.stack_args; 
     221                        ap.stack_args += 8; 
     222                    } 
     223                    // Be careful not to go past the size of the actual argument 
     224                    const sz2 = T.sizeof - 8; 
     225                    p[0..sz2] = a[0..sz2]; 
     226                } 
     227            } 
     228            else 
     229            { 
     230                static assert(0); 
     231            } 
    29232        } 
     233        else 
     234        { 
     235            static assert(0, "not a valid argument type for va_arg"); 
     236        } 
    30237    } 
    31238 
    32     template va_arg( T
     239    void va_arg()(va_list apx, TypeInfo ti, void* parmn
    33240    { 
    34         T va_arg( ref va_list ap ) 
     241        __va_list* ap = cast(__va_list*)apx; 
     242        TypeInfo arg1, arg2; 
     243        if (!ti.argTypes(arg1, arg2)) 
    35244        { 
    36             T arg = *cast(T*) ap; 
    37             ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 
    38             return arg; 
     245            if (arg1 && arg1.tsize() <= 8) 
     246            {   // Arg is passed in one register 
     247                auto tsize = arg1.tsize(); 
     248                void* p; 
     249                auto s = arg1.toString(); 
     250                if (s == "double" || s == "float") 
     251                {   // Passed in XMM register 
     252                    if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 
     253                    { 
     254                        p = ap.reg_args + ap.offset_fpregs; 
     255                        ap.offset_fpregs += 16; 
     256                    } 
     257                    else 
     258                    { 
     259                        p = ap.stack_args; 
     260                        ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     261                    } 
     262                } 
     263                else 
     264                {   // Passed in regular register 
     265                    if (ap.offset_regs < 6 * 8) 
     266                    { 
     267                        p = ap.reg_args + ap.offset_regs; 
     268                        ap.offset_regs += 8; 
     269                    } 
     270                    else 
     271                    { 
     272                        p = ap.stack_args; 
     273                        ap.stack_args += 8; 
     274                    } 
     275                } 
     276                parmn[0..tsize] = p[0..tsize]; 
     277 
     278                if (arg2) 
     279                { 
     280                    parmn += 8; 
     281                    tsize = arg2.tsize(); 
     282                    s = arg2.toString(); 
     283                    if (s == "double" || s == "float") 
     284                    {   // Passed in XMM register 
     285                        if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 
     286                        { 
     287                            p = ap.reg_args + ap.offset_fpregs; 
     288                            ap.offset_fpregs += 16; 
     289                        } 
     290                        else 
     291                        { 
     292                            p = ap.stack_args; 
     293                            ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 
     294                        } 
     295                    } 
     296                    else 
     297                    {   // Passed in regular register 
     298                        if (ap.offset_regs < 6 * 8) 
     299                        { 
     300                            p = ap.reg_args + ap.offset_regs; 
     301                            ap.offset_regs += 8; 
     302                        } 
     303                        else 
     304                        { 
     305                            p = ap.stack_args; 
     306                            ap.stack_args += 8; 
     307                        } 
     308                    } 
     309                    tsize = ti.tsize() - 8; 
     310                    parmn[0..tsize] = p[0..tsize]; 
     311                } 
     312            } 
     313            else 
     314            {   // Always passed in memory 
     315                // The arg may have more strict alignment than the stack 
     316                auto talign = ti.talign(); 
     317                auto tsize = ti.tsize(); 
     318                auto p = cast(void*)((cast(size_t)ap.stack_args + talign - 1) & ~(talign - 1)); 
     319                ap.stack_args = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 
     320                parmn[0..tsize] = p[0..tsize]; 
     321            } 
    39322        } 
     323        else 
     324        { 
     325            assert(0, "not a valid argument type for va_arg"); 
     326        } 
    40327    } 
    41328 
    42     void va_end( va_list ap
     329    void va_end(va_list ap
    43330    { 
    44  
    45331    } 
    46332 
    47     void va_copy( out va_list dest, va_list src
     333    void va_copy(out va_list dest, va_list src
    48334    { 
    49335        dest = src; 
    50336    } 
    51337} 
     338else 
     339{ 
     340    static assert(0); 
     341} 
     342}