view runtime/ldc.diff @ 698:f0ba5d37dd86

Merge darwin patch for Tango.
author Christian Kamm <kamm incasoftware de>
date Mon, 13 Oct 2008 16:51:38 +0200
parents 8d7e58801c82
children f34b552619fd
line wrap: on
line source

Index: object.di
===================================================================
--- object.di	(revision 4002)
+++ object.di	(working copy)
@@ -150,6 +150,9 @@
     void function() dtor;
     void function() unitTest;
 
+    void* xgetMembers;
+    void function() ictor;
+
     static int opApply( int delegate( inout ModuleInfo ) );
 }
 
Index: lib/common/tango/core/BitManip.d
===================================================================
--- lib/common/tango/core/BitManip.d	(revision 4002)
+++ lib/common/tango/core/BitManip.d	(working copy)
@@ -171,6 +171,10 @@
      */
     uint outpl( uint port_address, uint value );
 }
+else version( LDC )
+{
+    public import ldc.bitmanip;
+}
 else
 {
     public import std.intrinsic;
Index: lib/common/tango/core/Thread.d
===================================================================
--- lib/common/tango/core/Thread.d	(revision 4002)
+++ lib/common/tango/core/Thread.d	(working copy)
@@ -235,6 +235,7 @@
         // used to track the number of suspended threads
         //
         sem_t   suspendCount;
+        sem_t*  suspendCountPtr;
 
 
         extern (C) void thread_suspendHandler( int sig )
@@ -244,8 +245,29 @@
         }
         body
         {
-            version( D_InlineAsm_X86 )
+            version( LDC)
             {
+                version(X86)
+                {
+                    uint eax,ecx,edx,ebx,ebp,esi,edi;
+                    asm
+                    {
+                        mov eax[EBP], EAX      ;
+                        mov ecx[EBP], ECX      ;
+                        mov edx[EBP], EDX      ;
+                        mov ebx[EBP], EBX      ;
+                        mov ebp[EBP], EBP      ;
+                        mov esi[EBP], ESI      ;
+                        mov edi[EBP], EDI      ;
+                    }
+                }
+                else
+                {
+                    static assert( false, "Architecture not supported." );
+                }
+            }
+            else version( D_InlineAsm_X86 )
+            {
                 asm
                 {
                     pushad;
@@ -286,7 +308,7 @@
                 status = sigdelset( &sigres, SIGUSR2 );
                 assert( status == 0 );
 
-                status = sem_post( &suspendCount );
+                status = sem_post( suspendCountPtr );
                 assert( status == 0 );
 
                 sigsuspend( &sigres );
@@ -297,8 +319,12 @@
                 }
             }
 
-            version( D_InlineAsm_X86 )
+            version( LDC)
             {
+                // nothing to pop
+            }
+            else version( D_InlineAsm_X86 )
+            {
                 asm
                 {
                     popad;
@@ -1572,8 +1598,14 @@
         status = sigaction( SIGUSR2, &sigusr2, null );
         assert( status == 0 );
 
-        status = sem_init( &suspendCount, 0, 0 );
-        assert( status == 0 );
+        version(darwin){
+            suspendCountPtr = sem_open( "/thread_init/sem\0".ptr, 0 );
+            assert( suspendCountPtr !is null );
+        }else {
+            status=sem_init(&suspendCount,0,0);
+            suspendCountPtr=&suspendCount;
+            assert(status==0);
+        }
 
         status = pthread_key_create( &Thread.sm_this, null );
         assert( status == 0 );
@@ -1781,7 +1813,7 @@
                 //       to simply loop on sem_wait at the end, but I'm not
                 //       convinced that this would be much faster than the
                 //       current approach.
-                sem_wait( &suspendCount );
+                sem_wait( suspendCountPtr );
             }
             else if( !t.m_lock )
             {
@@ -2286,6 +2318,13 @@
             version = AsmPPC_Posix;
     }
 
+    version( LLVM_InlineAsm_X86 )
+    {
+        version( Win32 )
+            version = LLVM_AsmX86_Win32;
+        else version( Posix )
+            version = LLVM_AsmX86_Posix;
+    }
 
     version( Posix )
     {
@@ -2296,6 +2328,8 @@
         version( AsmX86_Win32 ) {} else
         version( AsmX86_Posix ) {} else
         version( AsmPPC_Posix ) {} else
+        version( LLVM_AsmX86_Win32 ) {} else
+        version( LLVM_AsmX86_Posix ) {} else
         {
             // NOTE: The ucontext implementation requires architecture specific
             //       data definitions to operate so testing for it must be done
@@ -2306,10 +2340,10 @@
             import tango.stdc.posix.ucontext;
         }
     }
-
-    const size_t PAGESIZE;
 }
 
+// this can't be private since it's used as default argument to a public function
+const size_t PAGESIZE;
 
 static this()
 {
@@ -2336,7 +2370,7 @@
     }
 }
 
-
+extern(C) int printf(char*, ...);
 ////////////////////////////////////////////////////////////////////////////////
 // Fiber Entry Point and Context Switch
 ////////////////////////////////////////////////////////////////////////////////
@@ -2450,6 +2484,22 @@
                 ret;
             }
         }
+        else version( LLVM_AsmX86_Posix )
+        {
+            asm
+            {
+                // clobber registers to save
+                inc EBX;
+                inc ESI;
+                inc EDI;
+
+                // store oldp again with more accurate address
+                mov EAX, oldp;
+                mov [EAX], ESP;
+                // load newp to begin context switch
+                mov ESP, newp;
+            }
+        }
         else static if( is( ucontext_t ) )
         {
             Fiber   cfib = Fiber.getThis();
@@ -3115,6 +3165,16 @@
             push( 0x00000000 );                                     // ESI
             push( 0x00000000 );                                     // EDI
         }
+        else version( LLVM_AsmX86_Posix )
+        {
+            push( cast(size_t) &fiber_entryPoint );                 // EIP
+            push( 0x00000000 );                                     // newp
+            push( 0x00000000 );                                     // oldp
+            push( 0x00000000 );                                     // EBP
+            push( 0x00000000 );                                     // EBX
+            push( 0x00000000 );                                     // ESI
+            push( 0x00000000 );                                     // EDI
+        }
         else version( AsmPPC_Posix )
         {
             version( StackGrowsDown )
Index: lib/unittest.sh
===================================================================
--- lib/unittest.sh	(revision 4002)
+++ lib/unittest.sh	(working copy)
@@ -18,8 +18,9 @@
   --help: This message
   --run-all: Reports result instead of breaking. Do not use this if you want to
          run unittest runner through a debugger.
-  dmd: Builds unittests for dmd
-  gdc: Builds unittests for gdc
+  dmd:    Builds unittests for dmd
+  gdc:    Builds unittests for gdc
+  ldc: Builds unittests for ldc
 
   <none>: Builds unittests for all known compilers.'
   exit 0
@@ -86,7 +87,7 @@
 void main() {}
 EOF
 
-        rebuild -w -d -g -L-ldl -L-lz -L-lbz2 -debug=UnitTest -debug -full -clean -unittest \
+        rebuild -w -d -L-ldl -L-lz -L-lbz2 -debug=UnitTest -debug -full -clean -unittest \
         -version=UnitTest $EXE.d tango/core/*.d tango/core/sync/*.d tango/io/digest/*.d \
         tango/io/model/*.d tango/io/protocol/*.d tango/io/selector/*.d tango/io/*.d \
         tango/io/vfs/*.d tango/io/vfs/model/*.d \
@@ -125,6 +126,9 @@
         gdc)
             GDC=1
             ;;
+        ldc)
+            LDC=1
+            ;;
         *)
             usage
             ;;
@@ -132,10 +136,11 @@
     shift
 done
 
-if [ ! "$DMD" -a ! "$GDC" ]
+if [ ! "$DMD" -a ! "$GDC" -a ! "$LDC" ]
 then
     DMD=1
     GDC=1
+    LDC=1
 fi
 
 if [ "$DMD" = "1" ]
@@ -146,4 +151,7 @@
 then
     compile gdc runUnitTest_gdc
 fi
-
+if [ "$LDC" = "1" ]
+then
+    compile ldc runUnitTest_ldc
+fi
Index: lib/gc/basic/gcx.d
===================================================================
--- lib/gc/basic/gcx.d	(revision 4002)
+++ lib/gc/basic/gcx.d	(working copy)
@@ -65,6 +65,13 @@
 }
 
 
+struct BlkInfo
+{
+    void*  base;
+    size_t size;
+    uint   attr;
+}
+
 private
 {
     enum BlkAttr : uint
@@ -75,13 +82,6 @@
         ALL_BITS = 0b1111_1111
     }
 
-    struct BlkInfo
-    {
-        void*  base;
-        size_t size;
-        uint   attr;
-    }
-
     extern (C) void* rt_stackBottom();
     extern (C) void* rt_stackTop();
 
@@ -2178,6 +2178,28 @@
             __builtin_unwind_init();
             sp = & sp;
         }
+        else version(LDC)
+        {
+            version(X86)
+            {
+                uint eax,ecx,edx,ebx,ebp,esi,edi;
+                asm
+                {
+                    mov eax[EBP], EAX      ;
+                    mov ecx[EBP], ECX      ;
+                    mov edx[EBP], EDX      ;
+                    mov ebx[EBP], EBX      ;
+                    mov ebp[EBP], EBP      ;
+                    mov esi[EBP], ESI      ;
+                    mov edi[EBP], EDI      ;
+                    mov sp[EBP],ESP     ;
+                }
+            }
+            else
+            {
+                static assert( false, "Architecture not supported." );
+            }
+        }
         else
         {
         asm
@@ -2191,6 +2213,10 @@
         {
             // nothing to do
         }
+        else version(LDC)
+        {
+            // nothing to do
+        }
         else
         {
         asm
Index: lib/gc/basic/gcbits.d
===================================================================
--- lib/gc/basic/gcbits.d	(revision 4002)
+++ lib/gc/basic/gcbits.d	(working copy)
@@ -39,6 +39,10 @@
 {
     // use the unoptimized version
 }
+else version(LDC)
+{
+    // ditto
+}
 else version (D_InlineAsm_X86)
 {
     version = Asm86;
Index: lib/build-tango.sh
===================================================================
--- lib/build-tango.sh	(revision 4002)
+++ lib/build-tango.sh	(working copy)
@@ -23,7 +23,7 @@
   --debug: Will enable debug info
   --warn: Will enable warnings
   --verbose: Increase verbosity 
-  <identifier> is one of {dmd, gdc, mac} and will build libtango.a,
+  <identifier> is one of {dmd, gdc, ldc, mac} and will build libtango.a,
                 libgtango.a or universal Mac binaries respectively
 
   The script must be called from within lib/ and the resulting
@@ -105,7 +105,7 @@
     if filter $OBJNAME
     then
         if [ $VERBOSE == 1 ]; then echo "[$DC] $FILENAME"; fi
-        $DC $WARN -c $INLINE $DEBUG $RELEASE -version=Posix -version=Tango -of$OBJNAME $FILENAME
+        $DC $WARN -c $INLINE $DEBUG $RELEASE -version=Tango -of$OBJNAME $FILENAME
         if [ "$?" != 0 ]
         then
             return 1;
@@ -189,6 +189,9 @@
         gdc)
             build gdmd libgtango.a libgphobos.a
             ;;
+        ldc)
+            build ldc libtango-user-ldc.a build-tango.sh
+            ;;
         mac)
             # build Universal Binary version of the Tango library
             build powerpc-apple-darwin8-gdmd libgtango.a.ppc libgphobos.a.ppc
Index: tango/text/convert/Layout.d
===================================================================
--- tango/text/convert/Layout.d	(revision 4002)
+++ tango/text/convert/Layout.d	(working copy)
@@ -47,6 +47,12 @@
         alias void* Arg;
         alias va_list ArgList;
         }
+else version(LDC)
+        {
+        private import tango.core.Vararg;
+        alias void* Arg;
+        alias va_list ArgList;
+        }
      else
         {
         alias void* Arg;
@@ -197,9 +203,18 @@
                 assert (formatStr, "null format specifier");
                 assert (arguments.length < 64, "too many args in Layout.convert");
 
-                version (GNU)
+                version (LDC)
                         {
                         Arg[64] arglist = void;
+                        foreach (i, arg; arguments)
+                                {
+                                arglist[i] = args;
+                                args += (arg.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1);
+                                }
+                        }
+                else version (GNU)
+                        {
+                        Arg[64] arglist = void;
                         int[64] intargs = void;
                         byte[64] byteargs = void;
                         long[64] longargs = void;
Index: tango/net/cluster/CacheInvalidator.d
===================================================================
--- tango/net/cluster/CacheInvalidator.d	(revision 4002)
+++ tango/net/cluster/CacheInvalidator.d	(working copy)
@@ -79,7 +79,7 @@
 
 *******************************************************************************/
 
-private class InvalidatorPayload : NetworkMessage
+package class InvalidatorPayload : NetworkMessage
 {
         private char[] key_;
 
Index: tango/core/Vararg.d
===================================================================
--- tango/core/Vararg.d	(revision 4002)
+++ tango/core/Vararg.d	(working copy)
@@ -15,6 +15,10 @@
 {
     public import std.stdarg;
 }
+else version( LDC )
+{
+    public import ldc.vararg;
+}
 else
 {
     /**
Index: tango/core/sync/Semaphore.d
===================================================================
--- tango/core/sync/Semaphore.d	(revision 3979)
+++ tango/core/sync/Semaphore.d	(working copy)
@@ -329,7 +329,8 @@
             {
                 synchronized( synComplete )
                 {
-                    if( numComplete == numConsumers )
+                    // if( numComplete == numConsumers )
+                    if( numComplete == numToProduce )
                         break;
                 }
                 Thread.yield();
@@ -337,9 +338,9 @@
 
             synchronized( synComplete )
             {
-                assert( numComplete == numConsumers );
+                assert( numComplete == numToProduce );
+                // assert( numComplete == numConsumers );
             }
-
             synchronized( synConsumed )
             {
                 assert( numConsumed == numToProduce );
@@ -400,7 +401,8 @@
 
     unittest
     {
+        version(darwin){}else{
         testWait();
-        testWaitTimeout();
+        testWaitTimeout();}
     }
 }
Index: tango/core/sync/Condition.d
===================================================================
--- tango/core/sync/Condition.d	(revision 3979)
+++ tango/core/sync/Condition.d	(working copy)
@@ -553,8 +553,11 @@
 
     unittest
     {
+        version(darwin){}
+        else{
         testNotify();
         testNotifyAll();
         testWaitTimeout();
+        }
     }
 }
Index: tango/core/Atomic.d
===================================================================
--- tango/core/Atomic.d	(revision 4002)
+++ tango/core/Atomic.d	(working copy)
@@ -270,6 +270,167 @@
 
 
 ////////////////////////////////////////////////////////////////////////////////
+// LDC Atomics Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+
+else version( LDC )
+{
+    import ldc.intrinsics;
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Atomic Load
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    template atomicLoad( msync ms = msync.seq, T )
+    {
+        T atomicLoad(ref T val)
+        {
+            llvm_memory_barrier(
+                ms == msync.hlb || ms == msync.acq || ms == msync.seq,
+                ms == msync.hsb || ms == msync.acq || ms == msync.seq,
+                ms == msync.slb || ms == msync.rel || ms == msync.seq,
+                ms == msync.ssb || ms == msync.rel || ms == msync.seq,
+                false);
+            static if (isPointerType!(T))
+            {
+                return cast(T)llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 0);
+            }
+            else static if (is(T == bool))
+            {
+                return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0;
+            }
+            else
+            {
+                return llvm_atomic_load_add!(T)(&val, cast(T)0);
+            }
+        }
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Atomic Store
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    template atomicStore( msync ms = msync.seq, T )
+    {
+        void atomicStore( ref T val, T newval )
+        {
+            llvm_memory_barrier(
+                ms == msync.hlb || ms == msync.acq || ms == msync.seq,
+                ms == msync.hsb || ms == msync.acq || ms == msync.seq,
+                ms == msync.slb || ms == msync.rel || ms == msync.seq,
+                ms == msync.ssb || ms == msync.rel || ms == msync.seq,
+                false);
+            static if (isPointerType!(T))
+            {
+                llvm_atomic_swap!(size_t)(cast(size_t*)&val, cast(size_t)newval);
+            }
+            else static if (is(T == bool))
+            {
+                llvm_atomic_swap!(ubyte)(cast(ubyte*)&val, newval?1:0);
+            }
+            else
+            {
+                llvm_atomic_swap!(T)(&val, newval);
+            }
+        }
+    }
+
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Atomic Store If
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    template atomicStoreIf( msync ms = msync.seq, T )
+    {
+        bool atomicStoreIf( ref T val, T newval, T equalTo )
+        {
+            llvm_memory_barrier(
+                ms == msync.hlb || ms == msync.acq || ms == msync.seq,
+                ms == msync.hsb || ms == msync.acq || ms == msync.seq,
+                ms == msync.slb || ms == msync.rel || ms == msync.seq,
+                ms == msync.ssb || ms == msync.rel || ms == msync.seq,
+                false);
+            T oldval = void;
+            static if (isPointerType!(T))
+            {
+                oldval = cast(T)llvm_atomic_cmp_swap!(size_t)(cast(size_t*)&val, cast(size_t)equalTo, cast(size_t)newval);
+            }
+            else static if (is(T == bool))
+            {
+                oldval = llvm_atomic_cmp_swap!(ubyte)(cast(ubyte*)&val, equalTo?1:0, newval?1:0)?0:1;
+            }
+            else
+            {
+                oldval = llvm_atomic_cmp_swap!(T)(&val, equalTo, newval);
+            }
+            return oldval == equalTo;
+        }
+    }
+    
+    
+    ////////////////////////////////////////////////////////////////////////////
+    // Atomic Increment
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    template atomicIncrement( msync ms = msync.seq, T )
+    {
+        //
+        // NOTE: This operation is only valid for integer or pointer types
+        //
+        static assert( isValidNumericType!(T) );
+
+
+        T atomicIncrement( ref T val )
+        {
+            static if (isPointerType!(T))
+            {
+                llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 1);
+            }
+            else
+            {
+                llvm_atomic_load_add!(T)(&val, cast(T)1);
+            }
+            return val;
+        }
+    }
+    
+    
+    ////////////////////////////////////////////////////////////////////////////
+    // Atomic Decrement
+    ////////////////////////////////////////////////////////////////////////////
+
+
+    template atomicDecrement( msync ms = msync.seq, T )
+    {
+        //
+        // NOTE: This operation is only valid for integer or pointer types
+        //
+        static assert( isValidNumericType!(T) );
+
+
+        T atomicDecrement( ref T val )
+        {
+            static if (isPointerType!(T))
+            {
+                llvm_atomic_load_sub!(size_t)(cast(size_t*)&val, 1);
+            }
+            else
+            {
+                llvm_atomic_load_sub!(T)(&val, cast(T)1);
+            }
+            return val;
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // x86 Atomic Function Implementation
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -282,9 +598,9 @@
         {
             pragma( msg, "tango.core.Atomic: using IA-32 inline asm" );
         }
-
+        version(darwin){}
+        else { version = Has64BitCAS; }
         version = Has32BitOps;
-        version = Has64BitCAS;
     }
     version( X86_64 )
     {
Index: tango/math/IEEE.d
===================================================================
--- tango/math/IEEE.d	(revision 3979)
+++ tango/math/IEEE.d	(working copy)
@@ -1543,7 +1543,12 @@
         else return 0;
      }  
  } else {
-    assert(0, "Unsupported");
+     static if (is(X==real)){
+         static assert(0, X.stringof~" unsupported by feqrel");
+     } else {
+         int res=feqrel(cast(real)x,cast(real)y);
+         return ((res>X.mant_dig)?X.mant_dig:res);
+     }
  }
 }
 
Index: tango/math/Math.d
===================================================================
--- tango/math/Math.d	(revision 4002)
+++ tango/math/Math.d	(working copy)
@@ -76,6 +76,14 @@
         version = DigitalMars_D_InlineAsm_X86;
     }
 }
+else version(LDC)
+{
+    import ldc.intrinsics;
+    version(X86)
+    {
+        version = LDC_X86;
+    }
+}
 
 /*
  * Constants
@@ -298,6 +306,24 @@
  * Bugs:
  *  Results are undefined if |x| >= $(POWER 2,64).
  */
+version(LDC)
+{
+    alias llvm_cos_f32 cos;
+    alias llvm_cos_f64 cos;
+    version(X86)
+    {
+        alias llvm_cos_f80 cos;
+    }
+    else
+    {
+        real cos(real x)
+        {
+            return tango.stdc.math.cosl(x);
+        }
+    }
+}
+else
+{
 real cos(real x) /* intrinsic */
 {
     version(D_InlineAsm_X86)
@@ -313,6 +339,7 @@
         return tango.stdc.math.cosl(x);
     }
 }
+}
 
 debug(UnitTest) {
 unittest {
@@ -333,6 +360,24 @@
  * Bugs:
  *  Results are undefined if |x| >= $(POWER 2,64).
  */
+version(LDC)
+{
+    alias llvm_sin_f32 sin;
+    alias llvm_sin_f64 sin;
+    version(X86)
+    {
+        alias llvm_sin_f80 sin;
+    }
+    else
+    {
+        real sin(real x)
+        {
+            return tango.stdc.math.sinl(x);
+        }
+    }
+}
+else
+{
 real sin(real x) /* intrinsic */
 {
     version(D_InlineAsm_X86)
@@ -348,6 +393,7 @@
         return tango.stdc.math.sinl(x);
     }
 }
+}
 
 debug(UnitTest) {
 unittest {
@@ -374,7 +420,11 @@
 {
     version (GNU) {
         return tanl(x);
-    } else {
+    }
+    else version(LDC) {
+        return tango.stdc.math.tanl(x);
+    }
+    else {
     asm
     {
         fld x[EBP]      ; // load theta
@@ -947,6 +997,25 @@
  *  <tr> <td> +&infin; <td> +&infin; <td> no
  *  )
  */
+version(LDC)
+{
+    alias llvm_sqrt_f32 sqrt;
+    alias llvm_sqrt_f64 sqrt;
+    version(X86)
+    {
+        alias llvm_sqrt_f80 sqrt;
+    }
+    else
+    {
+        real sqrt(real x)
+        {
+            return tango.stdc.math.sqrtl(x);
+        }
+    }
+}
+else
+{
+
 float sqrt(float x) /* intrinsic */
 {
     version(D_InlineAsm_X86)
@@ -995,6 +1064,8 @@
     }
 }
 
+}
+
 /** ditto */
 creal sqrt(creal z)
 {
@@ -1477,7 +1548,14 @@
         }
     }
     }
-    return tango.stdc.math.powl(x, y);
+    version(LDC_X86)
+    {
+        return llvm_pow_f80(x, y);
+    }
+    else
+    {
+        return tango.stdc.math.powl(x, y);
+    }
 }
 
 debug(UnitTest) {
Index: tango/stdc/posix/sys/types.d
===================================================================
--- tango/stdc/posix/sys/types.d	(revision 3979)
+++ tango/stdc/posix/sys/types.d	(working copy)
@@ -422,7 +422,11 @@
 }
 else version( darwin )
 {
-    struct pthread_spinlock_t;
+    version (LDC)
+        alias void* pthread_spinlock_t;
+        
+    else
+        struct pthread_spinlock_t;
 }
 else version( freebsd )
 {
Index: tango/stdc/stdlib.d
===================================================================
--- tango/stdc/stdlib.d	(revision 4002)
+++ tango/stdc/stdlib.d	(working copy)
@@ -94,6 +94,11 @@
 {
     void* alloca(size_t size);
 }
+else version( LDC )
+{
+    pragma(alloca)
+        void* alloca(size_t size);
+}
 else version( GNU )
 {
     private import gcc.builtins;
Index: tango/stdc/stdarg.d
===================================================================
--- tango/stdc/stdarg.d	(revision 4002)
+++ tango/stdc/stdarg.d	(working copy)
@@ -13,6 +13,10 @@
 {
     public import std.c.stdarg;
 }
+else version( LDC )
+{
+    public import ldc.cstdarg;
+}
 else
 {
     alias void* va_list;