changeset 443:44f08170f4ef

Removed tango from the repository and instead added a runtime dir with the files needed to patch and build tango from svn. Reworked the LLVMDC specific pragmas.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Fri, 01 Aug 2008 00:32:06 +0200
parents 76078c8ab5b9
children f2b5f86348ef
files bin/llvmdc.conf dmd/attrib.c dmd/declaration.h dmd/dsymbol.c dmd/dsymbol.h dmd/func.c dmd/id.c dmd/id.h dmd/idgen.c gen/enums.h gen/functions.cpp gen/structs.cpp gen/toir.cpp import/llvmdc/cstdarg.di import/llvmdc/intrinsics.di llvmdc-tango llvmdc.kdevelop runtime/README runtime/build.sh runtime/internal/aApply.d runtime/internal/aApplyR.d runtime/internal/aaA.d runtime/internal/adi.d runtime/internal/arrayInit.d runtime/internal/cast.d runtime/internal/critical.c runtime/internal/dmain2.d runtime/internal/eh.d runtime/internal/genobj.d runtime/internal/lifetime.d runtime/internal/llvmdc.mak runtime/internal/llvmdc/bitmanip.d runtime/internal/llvmdc/vararg.d runtime/internal/mars.h runtime/internal/memory.d runtime/internal/monitor.c runtime/internal/qsort2.d runtime/internal/switch.d runtime/internal/typeinfo/ti_AC.d runtime/internal/typeinfo/ti_Acdouble.d runtime/internal/typeinfo/ti_Acfloat.d runtime/internal/typeinfo/ti_Acreal.d runtime/internal/typeinfo/ti_Adouble.d runtime/internal/typeinfo/ti_Afloat.d runtime/internal/typeinfo/ti_Ag.d runtime/internal/typeinfo/ti_Aint.d runtime/internal/typeinfo/ti_Along.d runtime/internal/typeinfo/ti_Areal.d runtime/internal/typeinfo/ti_Ashort.d runtime/internal/typeinfo/ti_C.d runtime/internal/typeinfo/ti_byte.d runtime/internal/typeinfo/ti_cdouble.d runtime/internal/typeinfo/ti_cfloat.d runtime/internal/typeinfo/ti_char.d runtime/internal/typeinfo/ti_creal.d runtime/internal/typeinfo/ti_dchar.d runtime/internal/typeinfo/ti_delegate.d runtime/internal/typeinfo/ti_double.d runtime/internal/typeinfo/ti_float.d runtime/internal/typeinfo/ti_idouble.d runtime/internal/typeinfo/ti_ifloat.d runtime/internal/typeinfo/ti_int.d runtime/internal/typeinfo/ti_ireal.d runtime/internal/typeinfo/ti_long.d runtime/internal/typeinfo/ti_ptr.d runtime/internal/typeinfo/ti_real.d runtime/internal/typeinfo/ti_short.d runtime/internal/typeinfo/ti_ubyte.d runtime/internal/typeinfo/ti_uint.d runtime/internal/typeinfo/ti_ulong.d runtime/internal/typeinfo/ti_ushort.d runtime/internal/typeinfo/ti_void.d runtime/internal/typeinfo/ti_wchar.d runtime/internal/util/console.d runtime/internal/util/ctype.d runtime/internal/util/string.d runtime/internal/util/utf.d runtime/lib/common/tango/llvmdc.mak runtime/lib/gc/basic/llvmdc.mak runtime/lib/gc/stub/llvmdc.mak runtime/lib/llvmdc-posix.mak runtime/llvmdc.diff runtime/patch-tango.sh tango/LICENSE tango/README.txt tango/README_LLVMDC.txt tango/dsss.conf tango/example/cluster/Add.d tango/example/cluster/alert.d tango/example/cluster/cclient.d tango/example/cluster/cserver.d tango/example/cluster/invalidate.d tango/example/cluster/qclient.d tango/example/cluster/qlisten.d tango/example/cluster/qrequest.d tango/example/cluster/qserver.d tango/example/cluster/reply.d tango/example/cluster/task.d tango/example/cluster/tclient.d tango/example/cluster/tserver.d tango/example/concurrency/fiber_test.d tango/example/conduits/FileBucket.d tango/example/conduits/composite.d tango/example/conduits/filebubbler.d tango/example/conduits/filecat.d tango/example/conduits/filecopy.d tango/example/conduits/fileops.d tango/example/conduits/filepathname.d tango/example/conduits/filescan.d tango/example/conduits/filescanregex.d tango/example/conduits/lineio.d tango/example/conduits/mmap.d tango/example/conduits/paths.d tango/example/conduits/randomio.d tango/example/conduits/unifile.d tango/example/console/buffered.d tango/example/console/hello.d tango/example/console/stdout.d tango/example/dsss.conf tango/example/external/GlueFlectioned.d tango/example/jake-all.bat tango/example/linux.mak tango/example/logging/chainsaw.d tango/example/logging/context.d tango/example/logging/logging.d tango/example/logging/multilog.d tango/example/manual/chapterStorage.d tango/example/networking/homepage.d tango/example/networking/httpget.d tango/example/networking/selector.d tango/example/networking/sockethello.d tango/example/networking/socketserver.d tango/example/synchronization/barrier.d tango/example/synchronization/condition.d tango/example/synchronization/mutex.d tango/example/synchronization/readwritemutex.d tango/example/synchronization/semaphore.d tango/example/system/arguments.d tango/example/system/localtime.d tango/example/system/normpath.d tango/example/system/process.d tango/example/text/formatalign.d tango/example/text/formatindex.d tango/example/text/formatspec.d tango/example/text/localetime.d tango/example/text/properties.d tango/example/text/token.d tango/lib/common/tango/core/BitManip.d tango/lib/common/tango/core/Exception.d tango/lib/common/tango/core/Memory.d tango/lib/common/tango/core/Runtime.d tango/lib/common/tango/core/Thread.d tango/lib/common/tango/core/ThreadASM.S tango/lib/common/tango/llvmdc.mak tango/lib/common/tango/posix.mak tango/lib/common/tango/stdc/posix/pthread_darwin.d tango/lib/common/tango/stdc/wrap.c tango/lib/common/tango/stdc/wrap.ll tango/lib/common/tango/win32.mak tango/lib/compiler/llvmdc/aApply.d tango/lib/compiler/llvmdc/aApplyR.d tango/lib/compiler/llvmdc/aaA.d tango/lib/compiler/llvmdc/adi.d tango/lib/compiler/llvmdc/arrays.d tango/lib/compiler/llvmdc/cast.d tango/lib/compiler/llvmdc/critical.c tango/lib/compiler/llvmdc/dmain2.d tango/lib/compiler/llvmdc/eh.d tango/lib/compiler/llvmdc/genobj.d tango/lib/compiler/llvmdc/lifetime.d tango/lib/compiler/llvmdc/llvm/intrinsic.d tango/lib/compiler/llvmdc/llvmdc.mak tango/lib/compiler/llvmdc/mars.h tango/lib/compiler/llvmdc/memory.d tango/lib/compiler/llvmdc/monitor.c tango/lib/compiler/llvmdc/qsort2.d tango/lib/compiler/llvmdc/switch.d tango/lib/compiler/llvmdc/typeinfo/ti_AC.d tango/lib/compiler/llvmdc/typeinfo/ti_Acdouble.d tango/lib/compiler/llvmdc/typeinfo/ti_Acfloat.d tango/lib/compiler/llvmdc/typeinfo/ti_Acreal.d tango/lib/compiler/llvmdc/typeinfo/ti_Adouble.d tango/lib/compiler/llvmdc/typeinfo/ti_Afloat.d tango/lib/compiler/llvmdc/typeinfo/ti_Ag.d tango/lib/compiler/llvmdc/typeinfo/ti_Aint.d tango/lib/compiler/llvmdc/typeinfo/ti_Along.d tango/lib/compiler/llvmdc/typeinfo/ti_Areal.d tango/lib/compiler/llvmdc/typeinfo/ti_Ashort.d tango/lib/compiler/llvmdc/typeinfo/ti_C.d tango/lib/compiler/llvmdc/typeinfo/ti_byte.d tango/lib/compiler/llvmdc/typeinfo/ti_cdouble.d tango/lib/compiler/llvmdc/typeinfo/ti_cfloat.d tango/lib/compiler/llvmdc/typeinfo/ti_char.d tango/lib/compiler/llvmdc/typeinfo/ti_creal.d tango/lib/compiler/llvmdc/typeinfo/ti_dchar.d tango/lib/compiler/llvmdc/typeinfo/ti_delegate.d tango/lib/compiler/llvmdc/typeinfo/ti_double.d tango/lib/compiler/llvmdc/typeinfo/ti_float.d tango/lib/compiler/llvmdc/typeinfo/ti_idouble.d tango/lib/compiler/llvmdc/typeinfo/ti_ifloat.d tango/lib/compiler/llvmdc/typeinfo/ti_int.d tango/lib/compiler/llvmdc/typeinfo/ti_ireal.d tango/lib/compiler/llvmdc/typeinfo/ti_long.d tango/lib/compiler/llvmdc/typeinfo/ti_ptr.d tango/lib/compiler/llvmdc/typeinfo/ti_real.d tango/lib/compiler/llvmdc/typeinfo/ti_short.d tango/lib/compiler/llvmdc/typeinfo/ti_ubyte.d tango/lib/compiler/llvmdc/typeinfo/ti_uint.d tango/lib/compiler/llvmdc/typeinfo/ti_ulong.d tango/lib/compiler/llvmdc/typeinfo/ti_ushort.d tango/lib/compiler/llvmdc/typeinfo/ti_void.d tango/lib/compiler/llvmdc/typeinfo/ti_wchar.d tango/lib/compiler/llvmdc/util/console.d tango/lib/compiler/llvmdc/util/ctype.d tango/lib/compiler/llvmdc/util/string.d tango/lib/compiler/llvmdc/util/utf.d tango/lib/gc/basic/gc.d tango/lib/gc/basic/gcalloc.d tango/lib/gc/basic/gcbits.d tango/lib/gc/basic/gcstats.d tango/lib/gc/basic/gcx.d tango/lib/gc/basic/llvmdc.mak tango/lib/gc/basic/posix.mak tango/lib/gc/basic/win32.mak tango/lib/gc/stub/gc.d tango/lib/gc/stub/llvmdc.mak tango/lib/gc/stub/posix.mak tango/lib/gc/stub/win32.mak tango/lib/llvmdc-posix.mak tango/object.di tango/std/c/stdarg.di tango/std/intrinsic.di tango/std/stdarg.di tango/tango/core/Array.d tango/tango/core/Atomic.d tango/tango/core/BitArray.d tango/tango/core/BitManip.di tango/tango/core/ByteSwap.d tango/tango/core/Exception.di tango/tango/core/Memory.di tango/tango/core/Runtime.di tango/tango/core/Signal.d tango/tango/core/Thread.di tango/tango/core/Traits.d tango/tango/core/Tuple.d tango/tango/core/Vararg.d tango/tango/core/Variant.d tango/tango/core/Version.d tango/tango/core/sync/Barrier.d tango/tango/core/sync/Condition.d tango/tango/core/sync/Config.d tango/tango/core/sync/Mutex.d tango/tango/core/sync/ReadWriteMutex.d tango/tango/core/sync/Semaphore.d tango/tango/group/collection.d tango/tango/group/convert.d tango/tango/group/digest.d tango/tango/group/file.d tango/tango/group/http.d tango/tango/group/log.d tango/tango/group/math.d tango/tango/group/net.d tango/tango/group/stream.d tango/tango/group/text.d tango/tango/group/time.d tango/tango/io/Buffer.d tango/tango/io/Conduit.d tango/tango/io/Console.d tango/tango/io/DeviceConduit.d tango/tango/io/File.d tango/tango/io/FileConduit.d tango/tango/io/FileConst.d tango/tango/io/FilePath.d tango/tango/io/FileRoots.d tango/tango/io/FileScan.d tango/tango/io/FileSystem.d tango/tango/io/GrowBuffer.d tango/tango/io/MappedBuffer.d tango/tango/io/Print.d tango/tango/io/Stdout.d tango/tango/io/TempFile.d tango/tango/io/UnicodeFile.d tango/tango/io/archive/Zip.d tango/tango/io/compress/BzipStream.d tango/tango/io/compress/ZlibStream.d tango/tango/io/compress/c/bzlib.d tango/tango/io/compress/c/zlib.d tango/tango/io/digest/Crc32.d tango/tango/io/digest/Digest.d tango/tango/io/digest/Md2.d tango/tango/io/digest/Md4.d tango/tango/io/digest/Md5.d tango/tango/io/digest/MerkleDamgard.d tango/tango/io/digest/Sha0.d tango/tango/io/digest/Sha01.d tango/tango/io/digest/Sha1.d tango/tango/io/digest/Sha256.d tango/tango/io/digest/Sha512.d tango/tango/io/digest/Tiger.d tango/tango/io/model/IBuffer.d tango/tango/io/model/IConduit.d tango/tango/io/model/IListener.d tango/tango/io/protocol/Allocator.d tango/tango/io/protocol/EndianProtocol.d tango/tango/io/protocol/NativeProtocol.d tango/tango/io/protocol/PickleProtocol.d tango/tango/io/protocol/Reader.d tango/tango/io/protocol/Writer.d tango/tango/io/protocol/model/IProtocol.d tango/tango/io/protocol/model/IReader.d tango/tango/io/protocol/model/IWriter.d tango/tango/io/selector/AbstractSelector.d tango/tango/io/selector/EpollSelector.d tango/tango/io/selector/PollSelector.d tango/tango/io/selector/SelectSelector.d tango/tango/io/selector/Selector.d tango/tango/io/selector/SelectorException.d tango/tango/io/selector/model/ISelector.d tango/tango/io/stream/BufferStream.d tango/tango/io/stream/DataFileStream.d tango/tango/io/stream/DataStream.d tango/tango/io/stream/DigestStream.d tango/tango/io/stream/EndianStream.d tango/tango/io/stream/FileStream.d tango/tango/io/stream/FormatStream.d tango/tango/io/stream/GreedyStream.d tango/tango/io/stream/LineStream.d tango/tango/io/stream/MapStream.d tango/tango/io/stream/SnoopStream.d tango/tango/io/stream/TextFileStream.d tango/tango/io/stream/TypedStream.d tango/tango/io/stream/UtfStream.d tango/tango/io/vfs/FileFolder.d tango/tango/io/vfs/LinkedFolder.d tango/tango/io/vfs/VirtualFolder.d tango/tango/io/vfs/ZipArchive.d tango/tango/io/vfs/model/Vfs.d tango/tango/math/Bessel.d tango/tango/math/Elliptic.d tango/tango/math/ErrorFunction.d tango/tango/math/GammaFunction.d tango/tango/math/IEEE.d tango/tango/math/Math.d tango/tango/math/Probability.d tango/tango/math/Random.d tango/tango/net/DatagramConduit.d tango/tango/net/InternetAddress.d tango/tango/net/MulticastConduit.d tango/tango/net/ServerSocket.d tango/tango/net/Socket.d tango/tango/net/SocketConduit.d tango/tango/net/SocketListener.d tango/tango/net/Uri.d tango/tango/net/cluster/CacheInvalidatee.d tango/tango/net/cluster/CacheInvalidator.d tango/tango/net/cluster/NetworkAlert.d tango/tango/net/cluster/NetworkCache.d tango/tango/net/cluster/NetworkCall.d tango/tango/net/cluster/NetworkClient.d tango/tango/net/cluster/NetworkMessage.d tango/tango/net/cluster/NetworkQueue.d tango/tango/net/cluster/NetworkRegistry.d tango/tango/net/cluster/NetworkTask.d tango/tango/net/cluster/QueuedCache.d tango/tango/net/cluster/model/ICache.d tango/tango/net/cluster/model/IChannel.d tango/tango/net/cluster/model/ICluster.d tango/tango/net/cluster/model/IConsumer.d tango/tango/net/cluster/model/IMessage.d tango/tango/net/cluster/tina/CacheServer.d tango/tango/net/cluster/tina/CacheThread.d tango/tango/net/cluster/tina/Cluster.d tango/tango/net/cluster/tina/ClusterCache.d tango/tango/net/cluster/tina/ClusterQueue.d tango/tango/net/cluster/tina/ClusterServer.d tango/tango/net/cluster/tina/ClusterTask.d tango/tango/net/cluster/tina/ClusterThread.d tango/tango/net/cluster/tina/ClusterTypes.d tango/tango/net/cluster/tina/CmdParser.d tango/tango/net/cluster/tina/ProtocolReader.d tango/tango/net/cluster/tina/ProtocolWriter.d tango/tango/net/cluster/tina/QueueFile.d tango/tango/net/cluster/tina/QueueServer.d tango/tango/net/cluster/tina/QueueThread.d tango/tango/net/cluster/tina/RollCall.d tango/tango/net/cluster/tina/TaskServer.d tango/tango/net/cluster/tina/TaskThread.d tango/tango/net/cluster/tina/util/AbstractServer.d tango/tango/net/cluster/tina/util/ServerThread.d tango/tango/net/cluster/tina/util/model/IServer.d tango/tango/net/ftp/FtpClient.d tango/tango/net/ftp/Telnet.d tango/tango/net/http/ChunkStream.d tango/tango/net/http/HttpClient.d tango/tango/net/http/HttpConst.d tango/tango/net/http/HttpCookies.d tango/tango/net/http/HttpGet.d tango/tango/net/http/HttpHeaders.d tango/tango/net/http/HttpParams.d tango/tango/net/http/HttpPost.d tango/tango/net/http/HttpStack.d tango/tango/net/http/HttpTokens.d tango/tango/net/http/HttpTriplet.d tango/tango/net/http/model/HttpParamsView.d tango/tango/net/model/UriView.d tango/tango/stdc/complex.d tango/tango/stdc/config.d tango/tango/stdc/ctype.d tango/tango/stdc/errno.d tango/tango/stdc/fenv.d tango/tango/stdc/inttypes.d tango/tango/stdc/limits.d tango/tango/stdc/locale.d tango/tango/stdc/math.d tango/tango/stdc/posix/arpa/inet.d tango/tango/stdc/posix/config.d tango/tango/stdc/posix/dirent.d tango/tango/stdc/posix/dlfcn.d tango/tango/stdc/posix/fcntl.d tango/tango/stdc/posix/inttypes.d tango/tango/stdc/posix/net/if_.d tango/tango/stdc/posix/netinet/in_.d tango/tango/stdc/posix/netinet/tcp.d tango/tango/stdc/posix/poll.d tango/tango/stdc/posix/pthread.d tango/tango/stdc/posix/pwd.d tango/tango/stdc/posix/sched.d tango/tango/stdc/posix/semaphore.d tango/tango/stdc/posix/setjmp.d tango/tango/stdc/posix/signal.d tango/tango/stdc/posix/stdio.d tango/tango/stdc/posix/stdlib.d tango/tango/stdc/posix/sys/ipc.d tango/tango/stdc/posix/sys/mman.d tango/tango/stdc/posix/sys/select.d tango/tango/stdc/posix/sys/shm.d tango/tango/stdc/posix/sys/socket.d tango/tango/stdc/posix/sys/stat.d tango/tango/stdc/posix/sys/time.d tango/tango/stdc/posix/sys/types.d tango/tango/stdc/posix/sys/uio.d tango/tango/stdc/posix/sys/wait.d tango/tango/stdc/posix/time.d tango/tango/stdc/posix/ucontext.d tango/tango/stdc/posix/unistd.d tango/tango/stdc/posix/utime.d tango/tango/stdc/signal.d tango/tango/stdc/stdarg.d tango/tango/stdc/stddef.d tango/tango/stdc/stdint.d tango/tango/stdc/stdio.d tango/tango/stdc/stdlib.d tango/tango/stdc/string.d tango/tango/stdc/stringz.d tango/tango/stdc/tgmath.d tango/tango/stdc/time.d tango/tango/stdc/wctype.d tango/tango/sys/Common.d tango/tango/sys/Environment.d tango/tango/sys/Pipe.d tango/tango/sys/Process.d tango/tango/sys/SharedLib.d tango/tango/sys/darwin/darwin.d tango/tango/sys/linux/epoll.d tango/tango/sys/linux/linux.d tango/tango/sys/linux/socket.d tango/tango/sys/win32/CodePage.d tango/tango/sys/win32/Macros.di tango/tango/sys/win32/Process.di tango/tango/sys/win32/Types.di tango/tango/sys/win32/UserGdi.di tango/tango/text/Ascii.d tango/tango/text/Properties.d tango/tango/text/Regex.d tango/tango/text/Text.d tango/tango/text/Unicode.d tango/tango/text/UnicodeData.d tango/tango/text/Util.d tango/tango/text/convert/Float.d tango/tango/text/convert/Format.d tango/tango/text/convert/Integer.d tango/tango/text/convert/Layout.d tango/tango/text/convert/Sprint.d tango/tango/text/convert/TimeStamp.d tango/tango/text/convert/UnicodeBom.d tango/tango/text/convert/Utf.d tango/tango/text/locale/Collation.d tango/tango/text/locale/Convert.d tango/tango/text/locale/Core.d tango/tango/text/locale/Data.d tango/tango/text/locale/Locale.d tango/tango/text/locale/Parse.d tango/tango/text/locale/Posix.d tango/tango/text/locale/Win32.d tango/tango/text/stream/LineIterator.d tango/tango/text/stream/QuoteIterator.d tango/tango/text/stream/RegexIterator.d tango/tango/text/stream/SimpleIterator.d tango/tango/text/stream/StreamIterator.d tango/tango/time/Clock.d tango/tango/time/ISO8601.d tango/tango/time/StopWatch.d tango/tango/time/Time.d tango/tango/time/WallClock.d tango/tango/time/chrono/Calendar.d tango/tango/time/chrono/Gregorian.d tango/tango/time/chrono/GregorianBased.d tango/tango/time/chrono/Hebrew.d tango/tango/time/chrono/Hijri.d tango/tango/time/chrono/Japanese.d tango/tango/time/chrono/Korean.d tango/tango/time/chrono/Taiwan.d tango/tango/time/chrono/ThaiBuddhist.d tango/tango/util/ArgParser.d tango/tango/util/Arguments.d tango/tango/util/Convert.d tango/tango/util/PathUtil.d tango/tango/util/collection/ArrayBag.d tango/tango/util/collection/ArraySeq.d tango/tango/util/collection/CircularSeq.d tango/tango/util/collection/HashMap.d tango/tango/util/collection/HashSet.d tango/tango/util/collection/LinkMap.d tango/tango/util/collection/LinkSeq.d tango/tango/util/collection/TreeBag.d tango/tango/util/collection/TreeMap.d tango/tango/util/collection/impl/AbstractIterator.d tango/tango/util/collection/impl/BagCollection.d tango/tango/util/collection/impl/CLCell.d tango/tango/util/collection/impl/Cell.d tango/tango/util/collection/impl/Collection.d tango/tango/util/collection/impl/DefaultComparator.d tango/tango/util/collection/impl/LLCell.d tango/tango/util/collection/impl/LLPair.d tango/tango/util/collection/impl/MapCollection.d tango/tango/util/collection/impl/RBCell.d tango/tango/util/collection/impl/RBPair.d tango/tango/util/collection/impl/SeqCollection.d tango/tango/util/collection/impl/SetCollection.d tango/tango/util/collection/iterator/ArrayIterator.d tango/tango/util/collection/iterator/FilteringIterator.d tango/tango/util/collection/iterator/InterleavingIterator.d tango/tango/util/collection/model/Bag.d tango/tango/util/collection/model/BagView.d tango/tango/util/collection/model/Comparator.d tango/tango/util/collection/model/Dispenser.d tango/tango/util/collection/model/GuardIterator.d tango/tango/util/collection/model/HashParams.d tango/tango/util/collection/model/Iterator.d tango/tango/util/collection/model/Map.d tango/tango/util/collection/model/MapView.d tango/tango/util/collection/model/Seq.d tango/tango/util/collection/model/SeqView.d tango/tango/util/collection/model/Set.d tango/tango/util/collection/model/SetView.d tango/tango/util/collection/model/Sortable.d tango/tango/util/collection/model/SortedKeys.d tango/tango/util/collection/model/SortedValues.d tango/tango/util/collection/model/View.d tango/tango/util/log/Appender.d tango/tango/util/log/Configurator.d tango/tango/util/log/ConsoleAppender.d tango/tango/util/log/DateLayout.d tango/tango/util/log/Event.d tango/tango/util/log/EventLayout.d tango/tango/util/log/FileAppender.d tango/tango/util/log/Hierarchy.d tango/tango/util/log/Log.d tango/tango/util/log/Log4Layout.d tango/tango/util/log/Logger.d tango/tango/util/log/MailAppender.d tango/tango/util/log/NullAppender.d tango/tango/util/log/PropertyConfigurator.d tango/tango/util/log/RollingFileAppender.d tango/tango/util/log/SocketAppender.d tango/tango/util/log/Trace.d tango/tango/util/log/model/IHierarchy.d tango/tango/util/log/model/ILevel.d tests/mini/alloca1.d tests/mini/arrays7.d tests/mini/bug44.d tests/mini/bug49.d tests/mini/bug50.d tests/mini/classes6.d tests/mini/intrinsics.d tests/mini/structs7.d tests/mini/union1.d tests/mini/union2.d tests/mini/union3.d tests/mini/union4.d tests/mini/union5.d tests/mini/union6.d tests/mini/union7.d tests/mini/vararg1.d
diffstat 594 files changed, 12810 insertions(+), 270264 deletions(-) [+]
line wrap: on
line diff
--- a/bin/llvmdc.conf	Thu Jul 31 19:14:49 2008 +0200
+++ b/bin/llvmdc.conf	Fri Aug 01 00:32:06 2008 +0200
@@ -1,4 +1,4 @@
 
 [Environment]
 
-DFLAGS=-I%@P%/../tango -L-L%@P%/../lib -R%@P%/../lib
+DFLAGS=-I%@P%/../tango -I%@P%/../tango/lib/common -I%@P%/../import -L-L%@P%/../lib -R%@P%/../lib
--- a/dmd/attrib.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/attrib.c	Fri Aug 01 00:32:06 2008 +0200
@@ -702,6 +702,20 @@
 
 /********************************* PragmaDeclaration ****************************/
 
+static bool parseStringExp(Expression* e, std::string& res)
+{
+    StringExp *s = NULL;
+
+    e = e->optimize(WANTvalue);
+    if (e->op == TOKstring && (s = (StringExp *)e))
+    {
+        char* str = (char*)s->string;
+        res = str;
+        return true;
+    }
+    return false;
+}
+
 PragmaDeclaration::PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl)
 	: AttribDeclaration(decl)
 {
@@ -725,7 +739,7 @@
 
 #if IN_LLVM
     int llvm_internal = 0;
-    char* llvm_str1 = NULL;
+    std::string arg1str;
 
 #endif
 
@@ -813,82 +827,93 @@
 	goto Lnodecl;
     }
 #endif
+
+// LLVMDC
 #if IN_LLVM
-    else if (ident == Id::LLVM_internal)
+
+    // pragma(intrinsic, dotExpS) { funcdecl(s) }
+    else if (ident == Id::intrinsic)
     {
-        if (!args || args->dim < 1 || args->dim > 2)
-            error("needs 1-3 parameters");
-        else if (!decl || decl->dim < 1)
-            error("must apply to at least one declaration");
-        else
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
         {
-            Expression *e;
-            StringExp *s = NULL;
+             error("pragma intrinsic requires exactly 1 string literal parameter");
+             fatal();
+        }
+        llvm_internal = LLVMintrinsic;
+    }
 
-            e = (Expression *)args->data[0];
-            e = e->semantic(sc);
-            e = e->optimize(WANTvalue);
-            if (e->op == TOKstring && (s = (StringExp *)e))
-            {
-                char* str = (char*)s->string;
-                if (strcmp(str,"intrinsic")==0) {
-                    llvm_internal = LLVMintrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"va_start")==0) {
-                    llvm_internal = LLVMva_start;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_arg")==0) {
-                    llvm_internal = LLVMva_arg;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"va_intrinsic")==0) {
-                    llvm_internal = LLVMva_intrinsic;
-                    assert(args->dim == 2);
-                }
-                else if (strcmp(str,"notypeinfo")==0) {
-                    llvm_internal = LLVMnotypeinfo;
-                    assert(args->dim == 1);
-                }
-                else if (strcmp(str,"alloca")==0) {
-                    llvm_internal = LLVMalloca;
-                    assert(args->dim == 1);
-                }
-                else {
-                    error("unknown pragma command: %s", str);
-                }
-            }
-            else
-            error("1st argument must be a string");
+    // pragma(va_intrinsic, dotExpS) { funcdecl(s) }
+    else if (ident == Id::va_intrinsic)
+    {
+        Expression* expr = (Expression *)args->data[0];
+        expr = expr->semantic(sc);
+        if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
+        {
+             error("pragma va_intrinsic requires exactly 1 string literal parameter");
+             fatal();
+        }
+        llvm_internal = LLVMva_intrinsic;
+    }
 
-            if (llvm_internal)
-            switch (llvm_internal)
-            {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                e = (Expression *)args->data[1];
-                e = e->semantic(sc);
-                e = e->optimize(WANTvalue);
-                if (e->op == TOKstring && (s = (StringExp *)e)) {
-                    llvm_str1 = (char*)s->string;
-                }
-                else
-                error("2nd argument must be a string");
-                break;
+    // pragma(notypeinfo) { typedecl(s) }
+    else if (ident == Id::no_typeinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma no_typeinfo takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_typeinfo;
+    }
 
-            case LLVMva_arg:
-            case LLVMva_start:
-            case LLVMnotypeinfo:
-            case LLVMalloca:
-                break;
+    // pragma(nomoduleinfo) ;
+    else if (ident == Id::no_moduleinfo)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma no_moduleinfo takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMno_moduleinfo;
+    }
 
-            default:
-                assert(0);
-            }
+    // pragma(alloca) { funcdecl(s) }
+    else if (ident == Id::alloca)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma alloca takes no parameters");
+             fatal();
         }
+        llvm_internal = LLVMalloca;
     }
-#endif
+
+    // pragma(va_start) { templdecl(s) }
+    else if (ident == Id::va_start)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma va_start takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_start;
+    }
+
+    // pragma(va_arg) { templdecl(s) }
+    else if (ident == Id::va_arg)
+    {
+        if (args && args->dim > 0)
+        {
+             error("pragma va_arg takes no parameters");
+             fatal();
+        }
+        llvm_internal = LLVMva_arg;
+    }
+
+#endif // LLVMDC
+
     else if (global.params.ignoreUnsupportedPragmas)
     {
 	if (global.params.verbose)
@@ -926,60 +951,84 @@
 	    Dsymbol *s = (Dsymbol *)decl->data[i];
 
 	    s->semantic(sc);
-        
+
+// LLVMDC
 #if IN_LLVM
+
         if (llvm_internal)
         {
-            switch(llvm_internal)
+        if (s->llvmInternal)
+        {
+            error("multiple LLVMDC specific pragmas not allowed not affect the same declaration (%s at '%s')", s->toChars(), s->loc.toChars());
+            fatal();
+        }
+        switch(llvm_internal)
+        {
+        case LLVMintrinsic:
+        case LLVMva_intrinsic:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
             {
-            case LLVMintrinsic:
-            case LLVMva_intrinsic:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                    fd->llvmInternal1 = llvm_str1;
+                fd->llvmInternal = llvm_internal;
+                fd->intrinsicName = arg1str;
+            }
+            else
+            {
+                error("intrinsic pragmas are only allowed to affect function declarations");
+                fatal();
+            }
+            break;
+
+        case LLVMva_start:
+        case LLVMva_arg:
+            if (TemplateDeclaration* td = s->isTemplateDeclaration())
+            {
+                if (td->parameters->dim != 1)
+                {
+                    error("the %s pragma template must have exactly one template parameter", ident->toChars());
+                    fatal();
                 }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
+                else if (!td->onemember)
+                {
+                    error("the %s pragma template must have exactly one member", ident->toChars());
+                    fatal();
                 }
-                break;
+                else if (td->overnext || td->overroot)
+                {
+                    error("the %s pragma template must not be overloaded", ident->toChars());
+                    fatal();
+                }
+                td->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the %s pragma is only allowed on template declarations", ident->toChars());
+                fatal();
+            }
+            break;
 
-            case LLVMva_start:
-            case LLVMva_arg:
-                if (TemplateDeclaration* td = s->isTemplateDeclaration()) {
-                    td->llvmInternal = llvm_internal;
-                    assert(td->parameters->dim == 1);
-                    assert(!td->overnext);
-                    assert(!td->overroot);
-                    assert(td->onemember);
-                    Logger::println("template->onemember = %s", td->onemember->toChars());
-                }
-                else {
-                    error("can only be used on templates");
-                    assert(0);
-                }
-                break;
+        case LLVMno_typeinfo:
+            s->llvmInternal = llvm_internal;
+            break;
 
-            case LLVMnotypeinfo:
-                s->llvmInternal = llvm_internal;
-                break;
+        case LLVMalloca:
+            if (FuncDeclaration* fd = s->isFuncDeclaration())
+            {
+                fd->llvmInternal = llvm_internal;
+            }
+            else
+            {
+                error("the %s pragma must only be used on function declarations of type 'void* function(uint nbytes)'", ident->toChars());
+                fatal();
+            }
+            break;
 
-            case LLVMalloca:
-                if (FuncDeclaration* fd = s->isFuncDeclaration()) {
-                    fd->llvmInternal = llvm_internal;
-                }
-                else {
-                    error("may only be used on function declarations");
-                    assert(0);
-                }
-                break;
+        default:
+            warning("LLVMDC specific pragma %s not yet implemented, ignoring", ident->toChars());
+        }
+        }
 
-            default:
-                assert(0 && "invalid LLVM_internal pragma got through :/");
-            }
-        }
-        
-#endif
+#endif // LLVMDC
+
     }
     }
     return;
--- a/dmd/declaration.h	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/declaration.h	Fri Aug 01 00:32:06 2008 +0200
@@ -17,6 +17,7 @@
 
 #include <set>
 #include <map>
+#include <string>
 
 #include "dsymbol.h"
 #include "lexer.h"
@@ -639,6 +640,7 @@
 
     // llvmdc stuff
     std::set<VarDeclaration*> nestedVars;
+    std::string intrinsicName;
 
     // we keep our own table of label statements as LabelDsymbolS
     // don't always carry their corresponding statement along ...
--- a/dmd/dsymbol.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/dsymbol.c	Fri Aug 01 00:32:06 2008 +0200
@@ -45,8 +45,6 @@
     this->comment = NULL;
 
     this->llvmInternal = LLVMnone;
-    this->llvmInternal1 = NULL;
-    this->llvmInternal2 = NULL;
 }
 
 Dsymbol::Dsymbol(Identifier *ident)
@@ -61,8 +59,6 @@
     this->comment = NULL;
 
     this->llvmInternal = LLVMnone;
-    this->llvmInternal1 = NULL;
-    this->llvmInternal2 = NULL;
 }
 
 int Dsymbol::equals(Object *o)
--- a/dmd/dsymbol.h	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/dsymbol.h	Fri Aug 01 00:32:06 2008 +0200
@@ -220,12 +220,10 @@
     virtual AttribDeclaration *isAttribDeclaration() { return NULL; }
     virtual TypeInfoDeclaration* isTypeInfoDeclaration() { return NULL; }
     virtual ClassInfoDeclaration* isClassInfoDeclaration() { return NULL; }
-    
+
     // llvm stuff
     int llvmInternal;
-    char* llvmInternal1;
-    char* llvmInternal2;
-    
+
     IrDsymbol ir;
 };
 
--- a/dmd/func.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/func.c	Fri Aug 01 00:32:06 2008 +0200
@@ -90,6 +90,10 @@
     f->fensure  = fensure  ? fensure->syntaxCopy()  : NULL;
     f->fbody    = fbody    ? fbody->syntaxCopy()    : NULL;
     assert(!fthrows); // deprecated
+
+    // LLVMDC
+    f->intrinsicName = intrinsicName;
+
     return f;
 }
 
--- a/dmd/id.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/id.c	Fri Aug 01 00:32:06 2008 +0200
@@ -167,11 +167,15 @@
 Identifier *Id::lib;
 Identifier *Id::msg;
 Identifier *Id::GNU_asm;
-Identifier *Id::LLVM_intrinsic;
-Identifier *Id::LLVM_internal;
+Identifier *Id::intrinsic;
+Identifier *Id::va_intrinsic;
+Identifier *Id::no_typeinfo;
+Identifier *Id::no_moduleinfo;
+Identifier *Id::alloca;
+Identifier *Id::va_start;
+Identifier *Id::va_arg;
 Identifier *Id::tohash;
 Identifier *Id::tostring;
-Identifier *Id::alloca;
 Identifier *Id::main;
 Identifier *Id::WinMain;
 Identifier *Id::DllMain;
@@ -342,11 +346,15 @@
     lib = Lexer::idPool("lib");
     msg = Lexer::idPool("msg");
     GNU_asm = Lexer::idPool("GNU_asm");
-    LLVM_intrinsic = Lexer::idPool("LLVM_intrinsic");
-    LLVM_internal = Lexer::idPool("LLVM_internal");
+    intrinsic = Lexer::idPool("intrinsic");
+    va_intrinsic = Lexer::idPool("va_intrinsic");
+    no_typeinfo = Lexer::idPool("no_typeinfo");
+    no_moduleinfo = Lexer::idPool("no_moduleinfo");
+    alloca = Lexer::idPool("alloca");
+    va_start = Lexer::idPool("va_start");
+    va_arg = Lexer::idPool("va_arg");
     tohash = Lexer::idPool("toHash");
     tostring = Lexer::idPool("toString");
-    alloca = Lexer::idPool("alloca");
     main = Lexer::idPool("main");
     WinMain = Lexer::idPool("WinMain");
     DllMain = Lexer::idPool("DllMain");
--- a/dmd/id.h	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/id.h	Fri Aug 01 00:32:06 2008 +0200
@@ -169,11 +169,15 @@
     static Identifier *lib;
     static Identifier *msg;
     static Identifier *GNU_asm;
-    static Identifier *LLVM_intrinsic;
-    static Identifier *LLVM_internal;
+    static Identifier *intrinsic;
+    static Identifier *va_intrinsic;
+    static Identifier *no_typeinfo;
+    static Identifier *no_moduleinfo;
+    static Identifier *alloca;
+    static Identifier *va_start;
+    static Identifier *va_arg;
     static Identifier *tohash;
     static Identifier *tostring;
-    static Identifier *alloca;
     static Identifier *main;
     static Identifier *WinMain;
     static Identifier *DllMain;
--- a/dmd/idgen.c	Thu Jul 31 19:14:49 2008 +0200
+++ b/dmd/idgen.c	Fri Aug 01 00:32:06 2008 +0200
@@ -212,15 +212,22 @@
     { "lib" },
     { "msg" },
     { "GNU_asm" },
-    { "LLVM_intrinsic" },
-    { "LLVM_internal" },
+
+    // LLVMDC pragma's
+    { "intrinsic" },
+    { "va_intrinsic" },
+    { "no_typeinfo" },
+    { "no_moduleinfo" },
+    { "alloca" },
+    { "va_start" },
+    { "va_arg" },
 
     // For toHash/toString
     { "tohash", "toHash" },
     { "tostring", "toString" },
 
     // Special functions
-    { "alloca" },
+    //{ "alloca" },
     { "main" },
     { "WinMain" },
     { "DllMain" },
--- a/gen/enums.h	Thu Jul 31 19:14:49 2008 +0200
+++ b/gen/enums.h	Fri Aug 01 00:32:06 2008 +0200
@@ -2,9 +2,10 @@
 {
     LLVMnone,
     LLVMintrinsic,
-    LLVMva_arg,
+    LLVMva_intrinsic,
+    LLVMno_typeinfo,
+    LLVMno_moduleinfo,
+    LLVMalloca,
     LLVMva_start,
-    LLVMva_intrinsic,
-    LLVMnotypeinfo,
-    LLVMalloca
+    LLVMva_arg
 };
--- a/gen/functions.cpp	Thu Jul 31 19:14:49 2008 +0200
+++ b/gen/functions.cpp	Fri Aug 01 00:32:06 2008 +0200
@@ -253,7 +253,7 @@
         assert(fn);
     }
     else if (fdecl->llvmInternal == LLVMva_intrinsic) {
-        fn = gIR->module->getOrInsertFunction(fdecl->llvmInternal1, fty);
+        fn = gIR->module->getOrInsertFunction(fdecl->intrinsicName, fty);
         assert(fn);
     }
     else
@@ -405,9 +405,9 @@
     }
 
     // mangled name
-    char* mangled_name;
+    const char* mangled_name;
     if (fdecl->llvmInternal == LLVMintrinsic)
-        mangled_name = fdecl->llvmInternal1;
+        mangled_name = fdecl->intrinsicName.c_str();
     else
         mangled_name = fdecl->mangle();
 
--- a/gen/structs.cpp	Thu Jul 31 19:14:49 2008 +0200
+++ b/gen/structs.cpp	Fri Aug 01 00:32:06 2008 +0200
@@ -361,7 +361,7 @@
     gIR->structs.pop_back();
 
     // emit typeinfo
-    if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo)
+    if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo)
         DtoTypeInfoOf(sd->type, false);
 }
 
--- a/gen/toir.cpp	Thu Jul 31 19:14:49 2008 +0200
+++ b/gen/toir.cpp	Fri Aug 01 00:32:06 2008 +0200
@@ -758,8 +758,11 @@
         FuncDeclaration* fndecl = dfnval->func;
         // va_start instruction
         if (fndecl->llvmInternal == LLVMva_start) {
-            // TODO
-            assert(0 && "va_start not yet implemented");
+            // llvm doesn't need the second param hence the override
+            Expression* exp = (Expression*)arguments->data[0];
+            DValue* expv = exp->toElem(p);
+            LLValue* arg = DtoBitCast(expv->getLVal(), getVoidPtrType());
+            return new DImValue(type, gIR->ir->CreateCall(GET_INTRINSIC_DECL(vastart), arg, ""));
         }
         // va_arg instruction
         else if (fndecl->llvmInternal == LLVMva_arg) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/import/llvmdc/cstdarg.di	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,29 @@
+/*
+ * vararg support for extern(C) functions
+ */
+
+module llvmdc.cstdarg;
+
+// Check for the right compiler
+version(LLVMDC)
+{
+    // OK
+}
+else
+{
+    static assert(false, "This module is only valid for LLVMDC");
+}
+
+alias void* va_list;
+
+pragma(va_start)
+    void va_start(T)(va_list ap, ref T);
+
+pragma(va_arg)
+    T va_arg(T)(va_list ap);
+
+pragma(va_intrinsic, "llvm.va_end")
+    void va_end(va_list args);
+
+pragma(va_intrinsic, "llvm.va_copy")
+    void va_copy(va_list dst, va_list src);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/import/llvmdc/intrinsics.di	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,267 @@
+/*
+ * This module holds declarations to LLVM intrinsics.
+ *
+ * See the LLVM language reference for more information:
+ *
+ * - http://llvm.org/docs/LangRef.html#intrinsics
+ *
+ */
+
+module llvmdc.intrinsics;
+
+// Check for the right compiler
+version(LLVMDC)
+{
+    // OK
+}
+else
+{
+    static assert(false, "This module is only valid for LLVMDC");
+}
+
+//
+// CODE GENERATOR INTRINSICS
+//
+
+
+// The 'llvm.returnaddress' intrinsic attempts to compute a target-specific value indicating the return address of the current function or one of its callers. 
+
+pragma(intrinsic, "llvm.returnaddress")
+    void* llvm_returnaddress(uint level);
+
+
+// The 'llvm.frameaddress' intrinsic attempts to return the target-specific frame pointer value for the specified stack frame. 
+
+pragma(intrinsic, "llvm.frameaddress")
+    void* llvm_frameaddress(uint level);
+
+
+// The 'llvm.stacksave' intrinsic is used to remember the current state of the function stack, for use with llvm.stackrestore. This is useful for implementing language features like scoped automatic variable sized arrays in C99. 
+
+pragma(intrinsic, "llvm.stacksave")
+    void* llvm_stacksave();
+
+
+// The 'llvm.stackrestore' intrinsic is used to restore the state of the function stack to the state it was in when the corresponding llvm.stacksave intrinsic executed. This is useful for implementing language features like scoped automatic variable sized arrays in C99. 
+
+pragma(intrinsic, "llvm.stackrestore")
+    void llvm_stackrestore(void* ptr);
+
+
+// The 'llvm.prefetch' intrinsic is a hint to the code generator to insert a prefetch instruction if supported; otherwise, it is a noop. Prefetches have no effect on the behavior of the program but can change its performance characteristics.
+
+pragma(intrinsic, "llvm.prefetch")
+    void llvm_prefetch(void* ptr, uint rw, uint locality);
+
+
+// The 'llvm.pcmarker' intrinsic is a method to export a Program Counter (PC) in a region of code to simulators and other tools. The method is target specific, but it is expected that the marker will use exported symbols to transmit the PC of the marker. The marker makes no guarantees that it will remain with any specific instruction after optimizations. It is possible that the presence of a marker will inhibit optimizations. The intended use is to be inserted after optimizations to allow correlations of simulation runs. 
+
+pragma(intrinsic, "llvm.pcmarker")
+    void llvm_pcmarker(uint id);
+
+
+// The 'llvm.readcyclecounter' intrinsic provides access to the cycle counter register (or similar low latency, high accuracy clocks) on those targets that support it. On X86, it should map to RDTSC. On Alpha, it should map to RPCC. As the backing counters overflow quickly (on the order of 9 seconds on alpha), this should only be used for small timings. 
+
+pragma(intrinsic, "llvm.readcyclecounter")
+    ulong readcyclecounter();
+
+
+
+
+//
+// STANDARD C LIBRARY INTRINSICS
+//
+
+
+// The 'llvm.memcpy.*' intrinsics copy a block of memory from the source location to the destination location.
+// Note that, unlike the standard libc function, the llvm.memcpy.* intrinsics do not return a value, and takes an extra alignment argument.
+
+pragma(intrinsic, "llvm.memcpy.i32")
+    void llvm_memcpy_i32(void* dst, void* src, uint len, uint alignment);
+pragma(intrinsic, "llvm.memcpy.i64")
+    void llvm_memcpy_i64(void* dst, void* src, ulong len, uint alignment);
+
+
+// The 'llvm.memmove.*' intrinsics move a block of memory from the source location to the destination location. It is similar to the 'llvm.memcpy' intrinsic but allows the two memory locations to overlap.
+// Note that, unlike the standard libc function, the llvm.memmove.* intrinsics do not return a value, and takes an extra alignment argument.
+
+pragma(intrinsic, "llvm.memmove.i32")
+    void llvm_memmove_i32(void* dst, void* src, uint len, uint alignment);
+pragma(intrinsic, "llvm.memmove.i64")
+    void llvm_memmove_i64(void* dst, void* src, ulong len, int alignment);
+
+
+// The 'llvm.memset.*' intrinsics fill a block of memory with a particular byte value.
+// Note that, unlike the standard libc function, the llvm.memset intrinsic does not return a value, and takes an extra alignment argument.
+
+pragma(intrinsic, "llvm.memset.i32")
+    void llvm_memset_i32(void* dst, ubyte val, uint len, uint alignment);
+pragma(intrinsic, "llvm.memset.i64")
+    void llvm_memset_i64(void* dst, ubyte val, ulong len, uint alignment);
+
+
+// The 'llvm.sqrt' intrinsics return the sqrt of the specified operand, returning the same value as the libm 'sqrt' functions would. Unlike sqrt in libm, however, llvm.sqrt has undefined behavior for negative numbers other than -0.0 (which allows for better optimization, because there is no need to worry about errno being set). llvm.sqrt(-0.0) is defined to return -0.0 like IEEE sqrt. 
+
+pragma(intrinsic, "llvm.sqrt.f32")
+    float llvm_sqrt_f32(float val);
+pragma(intrinsic, "llvm.sqrt.f64")
+    double llvm_sqrt_f64(double val);
+version(LLVM_X86_FP80)
+{
+pragma(intrinsic, "llvm.sqrt.f80")
+    real llvm_sqrt_f80(real val);
+}
+
+
+// The 'llvm.sin.*' intrinsics return the sine of the operand. 
+
+pragma(intrinsic, "llvm.sin.f32")
+    float llvm_sin_f32(float val);
+pragma(intrinsic, "llvm.sin.f64")
+    double llvm_sin_f64(double val);
+version(LLVM_X86_FP80)
+{
+pragma(intrinsic, "llvm.sin.f80")
+    real llvm_sin_f80(real val);
+}
+
+
+// The 'llvm.cos.*' intrinsics return the cosine of the operand. 
+
+pragma(intrinsic, "llvm.cos.f32")
+    float llvm_cos_f32(float val);
+pragma(intrinsic, "llvm.cos.f64")
+    double llvm_cos_f64(double val);
+version(LLVM_X86_FP80)
+{
+pragma(intrinsic, "llvm.cos.f80")
+    real llvm_cos_f80(real val);
+}
+
+
+// The 'llvm.powi.*' intrinsics return the first operand raised to the specified (positive or negative) power. The order of evaluation of multiplications is not defined. When a vector of floating point type is used, the second argument remains a scalar integer value. 
+
+pragma(intrinsic, "llvm.powi.f32")
+    float llvm_powi_f32(float val, int power);
+
+pragma(intrinsic, "llvm.powi.f64")
+    double llvm_powi_f64(double val, int power);
+version(LLVM_X86_FP80)
+{
+pragma(intrinsic, "llvm.powi.f80")
+    real llvm_powi_f80(real val, int power);
+}
+
+
+// The 'llvm.pow.*' intrinsics return the first operand raised to the specified (positive or negative) power. 
+
+pragma(intrinsic, "llvm.pow.f32")
+    float llvm_pow_f32(float val, float power);
+
+pragma(intrinsic, "llvm.pow.f64")
+    double llvm_pow_f64(double val, double power);
+version(LLVM_X86_FP80)
+{
+pragma(intrinsic, "llvm.pow.f80")
+    real llvm_pow_f80(real val, real power);
+}
+
+
+
+
+//
+// BIT MANIPULATION INTRINSICS
+//
+
+// The 'llvm.bswap' family of intrinsics is used to byte swap integer values with an even number of bytes (positive multiple of 16 bits). These are useful for performing operations on data that is not in the target's native byte order. 
+
+pragma(intrinsic, "llvm.bswap.i16.i16")
+    ushort llvm_bswap_i16(ushort val);
+
+pragma(intrinsic, "llvm.bswap.i32.i32")
+    uint llvm_bswap_i32(uint val);
+
+pragma(intrinsic, "llvm.bswap.i64.i64")
+    ulong llvm_bswap_i64(ulong val);
+
+
+// The 'llvm.ctpop' family of intrinsics counts the number of bits set in a value. 
+
+pragma(intrinsic, "llvm.ctpop.i8")
+    ubyte llvm_ctpop_i8(ubyte src);
+
+pragma(intrinsic, "llvm.ctpop.i16")
+    ushort llvm_ctpop_i16(ushort src);
+
+pragma(intrinsic, "llvm.ctpop.i32")
+    uint llvm_ctpop_i32(uint src);
+
+pragma(intrinsic, "llvm.ctpop.i64")
+    ulong llvm_ctpop_i64(ulong src);
+
+
+// The 'llvm.ctlz' family of intrinsic functions counts the number of leading zeros in a variable. 
+
+pragma(intrinsic, "llvm.ctlz.i8")
+    ubyte llvm_ctlz_i8(ubyte src);
+
+pragma(intrinsic, "llvm.ctlz.i16")
+    ushort llvm_ctlz_i16(ushort src);
+
+pragma(intrinsic, "llvm.ctlz.i32")
+    uint llvm_ctlz_i32(uint src);
+
+pragma(intrinsic, "llvm.ctlz.i64")
+    ulong llvm_ctlz_i64(ulong src);
+
+
+// The 'llvm.cttz' family of intrinsic functions counts the number of trailing zeros. 
+
+pragma(intrinsic, "llvm.cttz.i8")
+    ubyte llvm_cttz_i8(ubyte src);
+
+pragma(intrinsic, "llvm.cttz.i16")
+    ushort llvm_cttz_i16(ushort src);
+
+pragma(intrinsic, "llvm.cttz.i32")
+    uint llvm_cttz_i32(uint src);
+
+pragma(intrinsic, "llvm.cttz.i64")
+    ulong llvm_cttz_i64(ulong src);
+
+
+// The 'llvm.part.select' family of intrinsic functions selects a range of bits from an integer value and returns them in the same bit width as the original value.
+
+pragma(intrinsic, "llvm.part.select.i8")
+    ubyte llvm_part_select_i(ubyte val, uint loBit, uint hiBit);
+
+pragma(intrinsic, "llvm.part.select.i16")
+    ushort llvm_part_select_i(ushort val, uint loBit, uint hiBit);
+
+pragma(intrinsic, "llvm.part.select.i32")
+    uint llvm_part_select_i(uint val, uint loBit, uint hiBit);
+
+pragma(intrinsic, "llvm.part.select.i64")
+    ulong llvm_part_select_i(ulong val, uint loBit, uint hiBit);
+
+
+
+
+//
+// ATOMIC OPERATIONS AND SYNCHRONIZATION INTRINSICS
+//
+
+// TODO
+
+
+
+
+//
+// GENERAL INTRINSICS
+//
+
+
+// This intrinsics is lowered to the target dependent trap instruction. If the target does not have a trap instruction, this intrinsic will be lowered to the call of the abort() function. 
+
+pragma(intrinsic, "llvm.trap")
+    void llvm_trap();
--- a/llvmdc-tango	Thu Jul 31 19:14:49 2008 +0200
+++ b/llvmdc-tango	Fri Aug 01 00:32:06 2008 +0200
@@ -13,7 +13,7 @@
 noversion=GNU
 testversion=linux
 testversion=Unix
-version=Posix
+testversion=Posix
 testversion=Windows
 testversion=Win32
 testversion=Win64
@@ -29,6 +29,7 @@
 testversion=LittleEndian
 testversion=BigEndian
 testversion=LLVM64
+textversion=LLVM_X86_FP80
 
 
 [compile]
--- a/llvmdc.kdevelop	Thu Jul 31 19:14:49 2008 +0200
+++ b/llvmdc.kdevelop	Fri Aug 01 00:32:06 2008 +0200
@@ -362,6 +362,50 @@
       <path>tests/dstress/ifeq__.c</path>
       <path>tests/dstress/return__.c</path>
       <path>e2ir.c</path>
+      <path>tango-llvmdc</path>
+      <path>tango-llvmdc/lib</path>
+      <path>tango-llvmdc/lib/common</path>
+      <path>tango-llvmdc/lib/common/tango</path>
+      <path>tango-llvmdc/lib/common/tango/stdc</path>
+      <path>tango-llvmdc/lib/common/tango/stdc/wrap.c</path>
+      <path>tango-llvmdc/lib/compiler</path>
+      <path>tango-llvmdc/lib/compiler/dmd</path>
+      <path>tango-llvmdc/lib/compiler/dmd/complex.c</path>
+      <path>tango-llvmdc/lib/compiler/dmd/critical.c</path>
+      <path>tango-llvmdc/lib/compiler/dmd/deh.c</path>
+      <path>tango-llvmdc/lib/compiler/dmd/mars.h</path>
+      <path>tango-llvmdc/lib/compiler/dmd/monitor.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc</path>
+      <path>tango-llvmdc/lib/compiler/gdc/config</path>
+      <path>tango-llvmdc/lib/compiler/gdc/config/gen_config1.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/config/gen_math.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/config/gen_unix.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/config/makestruct.h</path>
+      <path>tango-llvmdc/lib/compiler/gdc/critical.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/deh.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc/aix_float.h</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_fdset.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_math.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_stdio.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_time.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/mars.h</path>
+      <path>tango-llvmdc/lib/compiler/gdc/memory_dyld.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/memory_freebsd.c</path>
+      <path>tango-llvmdc/lib/compiler/gdc/monitor.c</path>
+      <path>tango-llvmdc/lib/compiler/llvmdc</path>
+      <path>tango-llvmdc/lib/compiler/llvmdc/critical.c</path>
+      <path>tango-llvmdc/lib/compiler/llvmdc/mars.h</path>
+      <path>tango-llvmdc/lib/compiler/llvmdc/monitor.c</path>
+      <path>tango-llvmdc/patches</path>
+      <path>tango-llvmdc/patches/proposals</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd/monitor.c</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc</path>
+      <path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc/monitor.c</path>
     </blacklist>
     <build>
       <buildtool>make</buildtool>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/README	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,11 @@
+1) Do a checkout of tango trunk in the llvmdc root dir (along dmd, gen, runtime etc).
+
+    *    svn co http://svn.dsource.org/projects/tango/trunk ../tango
+
+2) Patch the runtime
+
+    *    sh patch-tango.sh
+
+3) Compile the runtime
+
+    *    sh build.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/build.sh	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# I'm no good bash scripter ...
+
+# copy imports
+cp -u internal/llvmdc/bitmanip.d ../import/llvmdc/bitmanip.di
+cp -u internal/llvmdc/vararg.d ../import/llvmdc/vararg.di
+
+# make the runtime
+cp -Ru lib ../tango
+cd ../tango/lib
+make -f llvmdc-posix.mak clean
+make -f llvmdc-posix.mak
+
+# install the runtime
+rm -f ../../lib/libtango-base-llvmdc-native.a
+cp -s `pwd`/libtango-base-llvmdc-native.a ../../lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/aApply.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,406 @@
+/**
+ * Part of the D programming language runtime library.
+ */
+
+/*
+ *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+/* This code handles decoding UTF strings for foreach loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+private import util.utf;
+
+/**********************************************
+ */
+
+// dg is D, but _aApplycd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplycd1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+            d = decode(aa, i);
+        else
+            i++;
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw1(char[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   d = decode(aa, i);
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+		w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+		w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            i++;
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc1(), len = %d\n", len);
+    for (i = 0; i < len; )
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            d = decode(aa, i);
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            i++;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
+    foreach (dchar d; aa)
+    {
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+	    w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+	    w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+
+/****************************************************************************/
+
+// dg is D, but _aApplycd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplycd2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & 0x80)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywd2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplycw2(char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplycw2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+
+        w = aa[i];
+        if (w & 0x80)
+        {   n = i;
+            d = decode(aa, n);
+            n -= i;
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+		w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+		w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        else
+            n = 1;
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t n;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplywc2(), len = %d\n", len);
+    for (i = 0; i < len; i += n)
+    {   dchar d;
+        wchar w;
+        char c;
+
+        w = aa[i];
+        if (w & ~0x7F)
+        {
+            char[4] buf;
+
+            n = i;
+            d = decode(aa, n);
+            n -= i;
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)w;
+            n = 1;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplydc2(), len = %d\n", len);
+    for (i = 0; i < len; i++)
+    {   dchar d;
+        char c;
+
+        d = aa[i];
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
+    foreach (size_t i, dchar d; aa)
+    {
+        wchar w;
+        auto j = i;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+	    w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&j, cast(void *)&w);
+            if (result)
+                break;
+	    w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&j, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/aApplyR.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,975 @@
+
+/**
+ * Part of the D programming language runtime library.
+ */
+
+/*
+ *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+/* This code handles decoding UTF strings for foreach_reverse loops.
+ * There are 6 combinations of conversions between char, wchar,
+ * and dchar, and 2 of each of those.
+ */
+
+private import util.utf;
+
+/**********************************************/
+/* 1 argument versions */
+
+// dg is D, but _aApplyRcd() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd1.unittest\n");
+
+    auto s = "hello"c;
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd1.unittest\n");
+
+    auto s = "hello"w;
+    int i;
+
+    foreach_reverse(dchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(dchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == '\U00100456'); break;
+            case 2:     assert(d == '\u1234'); break;
+            case 3:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw1.unittest\n");
+
+    auto s = "hello"c;
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc1.unittest\n");
+
+    auto s = "hello"w;
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0;)
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {
+            c = cast(char)d;
+        }
+        result = dg(cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc1.unittest\n");
+
+    auto s = "hello"d;
+    int i;
+
+    foreach_reverse(char d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(char d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xF4); break;
+            case 2:     assert(d == 0x80); break;
+            case 3:     assert(d == 0x91); break;
+            case 4:     assert(d == 0x96); break;
+            case 5:     assert(d == 0xE1); break;
+            case 6:     assert(d == 0x88); break;
+            case 7:     assert(d == 0xB4); break;
+            case 8:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw1.unittest\n");
+
+    auto s = "hello"d;
+    int i;
+
+    foreach_reverse(wchar d; s)
+    {
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(wchar d; s)
+    {
+        //printf("i = %d, d = %x\n", i, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); break;
+            case 1:     assert(d == 0xDBC1); break;
+            case 2:     assert(d == 0xDC56); break;
+            case 3:     assert(d == 0x1234); break;
+            case 4:     assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+
+/****************************************************************************/
+/* 2 argument versions */
+
+// dg is D, but _aApplyRcd2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
+{   int result;
+    size_t i;
+    size_t len = aa.length;
+
+    debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
+    for (i = len; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d & 0x80)
+        {   char c = cast(char)d;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcd2.unittest\n");
+
+    auto s = "hello"c;
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(d == 'b'); assert(k == 8); break;
+            case 1:     assert(d == '\U00100456'); assert(k == 4); break;
+            case 2:     assert(d == '\u1234'); assert(k == 1); break;
+            case 3:     assert(d == 'a'); assert(k == 0); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+        result = dg(&i, cast(void *)&d);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwd2.unittest\n");
+
+    auto s = "hello"w;
+    int i;
+
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, dchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == '\U00100456'); break;
+            case 2:     assert(k == 1); assert(d == '\u1234'); break;
+            case 3:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 4);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        wchar w;
+
+        i--;
+        w = aa[i];
+        if (w & 0x80)
+        {   char c = cast(char)w;
+            uint j;
+            uint m = 0x3F;
+            d = 0;
+            while ((c & 0xC0) != 0xC0)
+            {   if (i == 0)
+                    onUnicodeError("Invalid UTF-8 sequence", 0);
+                i--;
+                d |= (c & 0x3F) << j;
+                j += 6;
+                m >>= 1;
+                c = aa[i];
+            }
+            d |= (c & m) << j;
+
+            if (d <= 0xFFFF)
+                w = cast(wchar) d;
+            else
+            {
+                w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+                result = dg(&i, cast(void *)&w);
+                if (result)
+                    break;
+                w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+            }
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRcw2.unittest\n");
+
+    auto s = "hello"c;
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 8); assert(d == 'b'); break;
+            case 1:     assert(k == 4); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 4); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d;
+        char c;
+
+        i--;
+        d = aa[i];
+        if (d >= 0xDC00 && d <= 0xDFFF)
+        {   if (i == 0)
+                onUnicodeError("Invalid UTF-16 sequence", 0);
+            i--;
+            d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
+        }
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        c = cast(char)d;
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRwc2.unittest\n");
+
+    auto s = "hello"w;
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 4); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        char c;
+
+        if (d & ~0x7F)
+        {
+            char[4] buf;
+
+            auto b = toUTF8(buf, d);
+            foreach (char c2; b)
+            {
+                result = dg(&i, cast(void *)&c2);
+                if (result)
+                    return result;
+            }
+            continue;
+        }
+        else
+        {   c = cast(char)d;
+        }
+        result = dg(&i, cast(void *)&c);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdc2.unittest\n");
+
+    auto s = "hello"d;
+    int i;
+
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, char d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xF4); break;
+            case 2:     assert(k == 2); assert(d == 0x80); break;
+            case 3:     assert(k == 2); assert(d == 0x91); break;
+            case 4:     assert(k == 2); assert(d == 0x96); break;
+            case 5:     assert(k == 1); assert(d == 0xE1); break;
+            case 6:     assert(k == 1); assert(d == 0x88); break;
+            case 7:     assert(k == 1); assert(d == 0xB4); break;
+            case 8:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 9);
+}
+
+/*****************************/
+
+extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
+{   int result;
+
+    debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
+    for (size_t i = aa.length; i != 0; )
+    {   dchar d = aa[--i];
+        wchar w;
+
+        if (d <= 0xFFFF)
+            w = cast(wchar) d;
+        else
+        {
+            w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
+            result = dg(&i, cast(void *)&w);
+            if (result)
+                break;
+            w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
+        }
+        result = dg(&i, cast(void *)&w);
+        if (result)
+            break;
+    }
+    return result;
+}
+
+unittest
+{
+    debug(apply) printf("_aApplyRdw2.unittest\n");
+
+    auto s = "hello"d;
+    int i;
+
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        assert(k == 4 - i);
+        switch (i)
+        {
+            case 0:     assert(d == 'o'); break;
+            case 1:     assert(d == 'l'); break;
+            case 2:     assert(d == 'l'); break;
+            case 3:     assert(d == 'e'); break;
+            case 4:     assert(d == 'h'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+
+    s = "a\u1234\U00100456b";
+    i = 0;
+    foreach_reverse(k, wchar d; s)
+    {
+        //printf("i = %d, k = %d, d = %x\n", i, k, d);
+        switch (i)
+        {
+            case 0:     assert(k == 3); assert(d == 'b'); break;
+            case 1:     assert(k == 2); assert(d == 0xDBC1); break;
+            case 2:     assert(k == 2); assert(d == 0xDC56); break;
+            case 3:     assert(k == 1); assert(d == 0x1234); break;
+            case 4:     assert(k == 0); assert(d == 'a'); break;
+            default:    assert(0);
+        }
+        i++;
+    }
+    assert(i == 5);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/aaA.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,832 @@
+//_ aaA.d
+
+/**
+ * Part of the D programming language runtime library.
+ * Implementation of associative arrays.
+ */
+
+/*
+ *  Copyright (C) 2000-2008 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, subject to the following restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ *  Modified by Tomas Lindquist Olsen <tomas@famolsen.dk> for use with LLVMDC.
+ */
+
+private
+{
+    import tango.stdc.stdarg;
+    import tango.stdc.string;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+// Auto-rehash and pre-allocate - Dave Fladebo
+
+static size_t[] prime_list = [
+               97UL,            389UL,
+            1_543UL,          6_151UL,
+           24_593UL,         98_317UL,
+          393_241UL,      1_572_869UL,
+        6_291_469UL,     25_165_843UL,
+      100_663_319UL,    402_653_189UL,
+    1_610_612_741UL,  4_294_967_291UL,
+//  8_589_934_513UL, 17_179_869_143UL
+];
+
+// This is the type of the return value for dynamic arrays.
+struct Array
+{
+    size_t length;
+    void* ptr;
+}
+
+struct aaA
+{
+    aaA *left;
+    aaA *right;
+    hash_t hash;
+    /* key   */
+    /* value */
+}
+
+struct BB
+{
+    aaA*[] b;
+    size_t nodes;       // total number of aaA nodes
+    TypeInfo keyti;     // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet() 
+}
+
+/* This is the type actually seen by the programmer, although
+ * it is completely opaque.
+ */
+
+// LLVMDC doesn't pass structs in registers so no need to wrap it ...
+alias BB* AA;
+
+/**********************************
+ * Align to next pointer boundary, so that
+ * GC won't be faced with misaligned pointers
+ * in value.
+ */
+
+size_t aligntsize(size_t tsize)
+{
+    // Is pointer alignment on the x64 4 bytes or 8?
+    return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
+}
+
+extern (C):
+
+/*************************************************
+ * Invariant for aa.
+ */
+
+/+
+void _aaInvAh(aaA*[] aa)
+{
+    for (size_t i = 0; i < aa.length; i++)
+    {
+        if (aa[i])
+            _aaInvAh_x(aa[i]);
+    }
+}
+
+private int _aaCmpAh_x(aaA *e1, aaA *e2)
+{   int c;
+
+    c = e1.hash - e2.hash;
+    if (c == 0)
+    {
+        c = e1.key.length - e2.key.length;
+        if (c == 0)
+            c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
+    }
+    return c;
+}
+
+private void _aaInvAh_x(aaA *e)
+{
+    hash_t key_hash;
+    aaA *e1;
+    aaA *e2;
+
+    key_hash = getHash(e.key);
+    assert(key_hash == e.hash);
+
+    while (1)
+    {   int c;
+
+        e1 = e.left;
+        if (e1)
+        {
+            _aaInvAh_x(e1);             // ordinary recursion
+            do
+            {
+                c = _aaCmpAh_x(e1, e);
+                assert(c < 0);
+                e1 = e1.right;
+            } while (e1 != null);
+        }
+
+        e2 = e.right;
+        if (e2)
+        {
+            do
+            {
+                c = _aaCmpAh_x(e, e2);
+                assert(c < 0);
+                e2 = e2.left;
+            } while (e2 != null);
+            e = e.right;                // tail recursion
+        }
+        else
+            break;
+    }
+}
++/
+
+/****************************************************
+ * Determine number of entries in associative array.
+ */
+
+size_t _aaLen(AA aa)
+in
+{
+    //printf("_aaLen()+\n");
+    //_aaInv(aa);
+}
+out (result)
+{
+    size_t len = 0;
+
+    void _aaLen_x(aaA* ex)
+    {
+        auto e = ex;
+        len++;
+
+        while (1)
+        {
+            if (e.right)
+               _aaLen_x(e.right);
+            e = e.left;
+            if (!e)
+                break;
+            len++;
+        }
+    }
+
+    if (aa)
+    {
+        foreach (e; aa.b)
+        {
+            if (e)
+                _aaLen_x(e);
+        }
+    }
+    assert(len == result);
+
+    //printf("_aaLen()-\n");
+}
+body
+{
+    return aa ? aa.nodes : 0;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Add entry for key if it is not already there.
+ */
+
+void* _aaGet(AA* aa_arg, TypeInfo keyti, size_t valuesize, void* pkey)
+in
+{
+    assert(aa_arg);
+}
+out (result)
+{
+    assert(result);
+    assert(*aa_arg);
+    assert((*aa_arg).b.length);
+    //assert(_aaInAh(*aa, key));
+}
+body
+{
+    //auto pkey = cast(void *)(&valuesize + 1);
+    size_t i;
+    aaA *e;
+    auto keysize = aligntsize(keyti.tsize());
+
+    if (!*aa_arg)
+        *aa_arg = new BB();
+    auto aa = *aa_arg;
+    aa.keyti = keyti;
+
+    if (!aa.b.length)
+    {
+        alias aaA *pa;
+        auto len = prime_list[0];
+
+        aa.b = new pa[len];
+    }
+
+    auto key_hash = keyti.getHash(pkey);
+    //printf("hash = %d\n", key_hash);
+    i = key_hash % aa.b.length;
+    auto pe = &aa.b[i];
+    while ((e = *pe) !is null)
+    {
+        if (key_hash == e.hash)
+        {
+            auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                goto Lret;
+            pe = (c < 0) ? &e.left : &e.right;
+        }
+        else
+            pe = (key_hash < e.hash) ? &e.left : &e.right;
+    }
+
+    // Not found, create new elem
+    //printf("create new one\n");
+    size_t size = aaA.sizeof + keysize + valuesize;
+    e = cast(aaA *) gc_calloc(size);
+    memcpy(e + 1, pkey, keysize);
+    e.hash = key_hash;
+    *pe = e;
+
+    auto nodes = ++aa.nodes;
+    //printf("length = %d, nodes = %d\n", (*aa).length, nodes);
+    if (nodes > aa.b.length * 4)
+    {
+        _aaRehash(aa_arg,keyti);
+    }
+
+Lret:
+    return cast(void *)(e + 1) + keysize;
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Returns null if it is not already there.
+ */
+
+void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void *pkey)
+{
+    //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
+    if (!aa)
+        return null;
+
+    //auto pkey = cast(void *)(&valuesize + 1);
+    auto keysize = aligntsize(keyti.tsize());
+    auto len = aa.b.length;
+
+    if (len)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % len;
+        auto e = aa.b[i];
+        while (e !is null)
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+            if (c == 0)
+                return cast(void *)(e + 1) + keysize;
+                e = (c < 0) ? e.left : e.right;
+            }
+            else
+                e = (key_hash < e.hash) ? e.left : e.right;
+        }
+    }
+    return null;    // not found, caller will throw exception
+}
+
+
+/*************************************************
+ * Determine if key is in aa.
+ * Returns:
+ *      null    not in aa
+ *      !=null  in aa, return pointer to value
+ */
+
+void* _aaIn(AA aa, TypeInfo keyti, void *pkey)
+in
+{
+}
+out (result)
+{
+    //assert(result == 0 || result == 1);
+}
+body
+{
+    if (aa)
+    {
+        //auto pkey = cast(void *)(&keyti + 1);
+
+        //printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
+        auto len = aa.b.length;
+
+        if (len)
+        {
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            size_t i = key_hash % len;
+            auto e = aa.b[i];
+            while (e !is null)
+            {
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        return cast(void *)(e + 1) + aligntsize(keyti.tsize());
+                    e = (c < 0) ? e.left : e.right;
+                }
+                else
+                    e = (key_hash < e.hash) ? e.left : e.right;
+            }
+        }
+    }
+
+    // Not found
+    return null;
+}
+
+/*************************************************
+ * Delete key entry in aa[].
+ * If key is not in aa[], do nothing.
+ */
+
+void _aaDel(AA aa, TypeInfo keyti, void *pkey)
+{
+    //auto pkey = cast(void *)(&keyti + 1);
+    aaA *e;
+
+    if (aa && aa.b.length)
+    {
+        auto key_hash = keyti.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % aa.b.length;
+        auto pe = &aa.b[i];
+        while ((e = *pe) !is null) // null means not found
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = keyti.compare(pkey, e + 1);
+                if (c == 0)
+                {
+                    if (!e.left && !e.right)
+                    {
+                        *pe = null;
+                    }
+                    else if (e.left && !e.right)
+                    {
+                        *pe = e.left;
+                         e.left = null;
+                    }
+                    else if (!e.left && e.right)
+                    {
+                        *pe = e.right;
+                         e.right = null;
+                    }
+                    else
+                    {
+                        *pe = e.left;
+                        e.left = null;
+                        do
+                            pe = &(*pe).right;
+                        while (*pe);
+                        *pe = e.right;
+                        e.right = null;
+                    }
+
+                    aa.nodes--;
+                    gc_free(e);
+
+                    break;
+                }
+                pe = (c < 0) ? &e.left : &e.right;
+            }
+            else
+                pe = (key_hash < e.hash) ? &e.left : &e.right;
+        }
+    }
+}
+
+
+/********************************************
+ * Produce array of values from aa.
+ */
+
+Array _aaValues(AA aa, size_t keysize, size_t valuesize)
+in
+{
+    assert(keysize == aligntsize(keysize));
+}
+body
+{
+    size_t resi;
+    Array a;
+
+    void _aaValues_x(aaA* e)
+    {
+        do
+        {
+            memcpy(a.ptr + resi * valuesize,
+                   cast(byte*)e + aaA.sizeof + keysize,
+                   valuesize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaValues_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    if (aa)
+    {
+        a.length = _aaLen(aa);
+        a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
+                                      valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
+        resi = 0;
+        foreach (e; aa.b)
+        {
+            if (e)
+                _aaValues_x(e);
+        }
+        assert(resi == a.length);
+    }
+    return a;
+}
+
+
+/********************************************
+ * Rehash an array.
+ */
+
+void* _aaRehash(AA* paa, TypeInfo keyti)
+in
+{
+    //_aaInvAh(paa);
+}
+out (result)
+{
+    //_aaInvAh(result);
+}
+body
+{
+    BB newb;
+
+    void _aaRehash_x(aaA* olde)
+    {
+        while (1)
+        {
+            auto left = olde.left;
+            auto right = olde.right;
+            olde.left = null;
+            olde.right = null;
+
+            aaA *e;
+
+            //printf("rehash %p\n", olde);
+            auto key_hash = olde.hash;
+            size_t i = key_hash % newb.b.length;
+            auto pe = &newb.b[i];
+            while ((e = *pe) !is null)
+            {
+                //printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
+                assert(e.left != e);
+                assert(e.right != e);
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(olde + 1, e + 1);
+                    assert(c != 0);
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            *pe = olde;
+
+            if (right)
+            {
+                if (!left)
+                {   olde = right;
+                    continue;
+                }
+                _aaRehash_x(right);
+            }
+            if (!left)
+                break;
+            olde = left;
+        }
+    }
+
+    //printf("Rehash\n");
+    if (*paa)
+    {
+        auto aa = *paa;
+        auto len = _aaLen(aa);
+        if (len)
+        {   size_t i;
+
+            for (i = 0; i < prime_list.length - 1; i++)
+            {
+                if (len <= prime_list[i])
+                    break;
+            }
+            len = prime_list[i];
+            newb.b = new aaA*[len];
+            newb.keyti = keyti;
+
+            foreach (e; aa.b)
+            {
+                if (e)
+                    _aaRehash_x(e);
+            }
+
+            newb.nodes = (*aa).nodes;
+        }
+
+        **paa = newb;
+    }
+    return *paa;
+}
+
+
+/********************************************
+ * Produce array of N byte keys from aa.
+ */
+
+Array _aaKeys(AA aa, size_t keysize)
+{
+    byte[] res;
+    size_t resi;
+
+    void _aaKeys_x(aaA* e)
+    {
+        do
+        {
+            memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
+            resi++;
+            if (e.left)
+            {   if (!e.right)
+                {   e = e.left;
+                    continue;
+                }
+                _aaKeys_x(e.left);
+            }
+            e = e.right;
+        } while (e !is null);
+    }
+
+    auto len = _aaLen(aa);
+    if (!len)
+        return Array();
+    res = (cast(byte*) gc_malloc(len * keysize,
+                                 !(aa.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0)) [0 .. len * keysize];
+    resi = 0;
+    foreach (e; aa.b)
+    {
+        if (e)
+            _aaKeys_x(e);
+    }
+    assert(resi == len);
+
+    return Array(len, res.ptr);
+}
+
+
+/**********************************************
+ * 'apply' for associative arrays - to support foreach
+ */
+
+// dg is D, but _aaApply() is C
+extern (D) typedef int delegate(void *) dg_t;
+
+int _aaApply(AA aa, size_t keysize, dg_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa)
+    {
+        foreach (e; aa.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+// dg is D, but _aaApply2() is C
+extern (D) typedef int delegate(void *, void *) dg2_t;
+
+int _aaApply2(AA aa, size_t keysize, dg2_t dg)
+in
+{
+    assert(aligntsize(keysize) == keysize);
+}
+body
+{   int result;
+
+    //printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
+
+    int treewalker(aaA* e)
+    {   int result;
+
+        do
+        {
+            //printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
+            result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
+            if (result)
+                break;
+            if (e.right)
+            {   if (!e.left)
+                {
+                    e = e.right;
+                    continue;
+                }
+                result = treewalker(e.right);
+                if (result)
+                    break;
+            }
+            e = e.left;
+        } while (e);
+
+        return result;
+    }
+
+    if (aa)
+    {
+        foreach (e; aa.b)
+        {
+            if (e)
+            {
+                result = treewalker(e);
+                if (result)
+                    break;
+            }
+        }
+    }
+    return result;
+}
+
+
+/***********************************
+ * Construct an associative array of type ti from
+ * length pairs of key/value pairs.
+ */
+
+/+
+
+extern (C)
+BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
+{
+    auto valuesize = ti.next.tsize();           // value size
+    auto keyti = ti.key;
+    auto keysize = keyti.tsize();               // key size
+    BB* result;
+
+    //printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
+    //printf("tivalue = %.*s\n", ti.next.classinfo.name);
+    if (length == 0 || valuesize == 0 || keysize == 0)
+    {
+        ;
+    }
+    else
+    {
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        result = new BB();
+        size_t i;
+
+        for (i = 0; i < prime_list.length - 1; i++)
+        {
+            if (length <= prime_list[i])
+                break;
+        }
+        auto len = prime_list[i];
+        result.b = new aaA*[len];
+
+        size_t keystacksize   = (keysize   + int.sizeof - 1) & ~(int.sizeof - 1);
+        size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        size_t keytsize = aligntsize(keysize);
+
+        for (size_t j = 0; j < length; j++)
+        {   void* pkey = q;
+            q += keystacksize;
+            void* pvalue = q;
+            q += valuestacksize;
+            aaA* e;
+
+            auto key_hash = keyti.getHash(pkey);
+            //printf("hash = %d\n", key_hash);
+            i = key_hash % len;
+            auto pe = &result.b[i];
+            while (1)
+            {
+                e = *pe;
+                if (!e)
+                {
+                    // Not found, create new elem
+                    //printf("create new one\n");
+                    e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
+                    memcpy(e + 1, pkey, keysize);
+                    e.hash = key_hash;
+                    *pe = e;
+                    result.nodes++;
+                    break;
+                }
+                if (key_hash == e.hash)
+                {
+                    auto c = keyti.compare(pkey, e + 1);
+                    if (c == 0)
+                        break;
+                    pe = (c < 0) ? &e.left : &e.right;
+                }
+                else
+                    pe = (key_hash < e.hash) ? &e.left : &e.right;
+            }
+            memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
+        }
+
+        va_end(q);
+    }
+    return result;
+}
+
++/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/adi.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,589 @@
+//_ adi.d
+
+/**
+ * Part of the D programming language runtime library.
+ * Dynamic array property support routines
+ */
+
+/*
+ *  Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+
+//debug=adi;            // uncomment to turn on debugging printf's
+
+private
+{
+    import tango.stdc.string;
+    import tango.stdc.stdlib;
+    import util.utf;
+
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) void  gc_free( void* p );
+}
+
+
+struct Array
+{
+    size_t  length;
+    void*   ptr;
+}
+
+/**********************************************
+ * Reverse array of chars.
+ * Handled separately because embedded multibyte encodings should not be
+ * reversed.
+ */
+
+extern (C) Array _adReverseChar(char[] a)
+{
+    if (a.length > 1)
+    {
+        char[6] tmp;
+        char[6] tmplo;
+        char* lo = a.ptr;
+        char* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+	    debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
+            if (clo <= 0x7F && chi <= 0x7F)
+            {
+		debug(adi) printf("\tascii\n");
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            uint stridelo = UTF8stride[clo];
+
+            uint stridehi = 1;
+            while ((chi & 0xC0) == 0x80)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+	    debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
+            if (stridelo == stridehi)
+            {
+
+                memcpy(tmp.ptr, lo, stridelo);
+                memcpy(lo, hi, stridelo);
+                memcpy(hi, tmp.ptr, stridelo);
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi);
+            memcpy(tmplo.ptr, lo, stridelo);
+            memmove(lo + stridehi, lo + stridelo , cast(size_t)(hi - lo) - stridelo);
+            memcpy(lo, tmp.ptr, stridehi);
+            memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return Array(a.length, a.ptr);
+}
+
+unittest
+{
+    auto a = "abcd"c;
+
+    auto r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "dcba");
+
+    a = "a\u1235\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234\u1235a");
+
+    a = "ab\u1234c";
+    //writefln(a);
+    r = a.dup.reverse;
+    //writefln(r);
+    assert(r == "c\u1234ba");
+
+    a = "\u3026\u2021\u3061\n";
+    r = a.dup.reverse;
+    assert(r == "\n\u3061\u2021\u3026");
+}
+
+
+/**********************************************
+ * Reverse array of wchars.
+ * Handled separately because embedded multiword encodings should not be
+ * reversed.
+ */
+
+extern (C) Array _adReverseWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+        wchar[2] tmp;
+        wchar* lo = a.ptr;
+        wchar* hi = &a[length - 1];
+
+        while (lo < hi)
+        {   auto clo = *lo;
+            auto chi = *hi;
+
+            if ((clo < 0xD800 || clo > 0xDFFF) &&
+                (chi < 0xD800 || chi > 0xDFFF))
+            {
+                *lo = chi;
+                *hi = clo;
+                lo++;
+                hi--;
+                continue;
+            }
+
+            int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
+
+            int stridehi = 1;
+            if (chi >= 0xDC00 && chi <= 0xDFFF)
+            {
+                chi = *--hi;
+                stridehi++;
+                assert(hi >= lo);
+            }
+            if (lo == hi)
+                break;
+
+            if (stridelo == stridehi)
+            {   int stmp;
+
+                assert(stridelo == 2);
+                assert(stmp.sizeof == 2 * (*lo).sizeof);
+                stmp = *cast(int*)lo;
+                *cast(int*)lo = *cast(int*)hi;
+                *cast(int*)hi = stmp;
+                lo += stridelo;
+                hi--;
+                continue;
+            }
+
+            /* Shift the whole array. This is woefully inefficient
+             */
+            memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
+            memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
+            memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
+            memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
+
+            lo += stridehi;
+            hi = hi - 1 + (stridehi - stridelo);
+        }
+    }
+    return Array(a.length, a.ptr);
+}
+
+unittest
+{
+    wstring a = "abcd";
+    wstring r;
+
+    r = a.dup.reverse;
+    assert(r == "dcba");
+
+    a = "a\U00012356\U00012346c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012346\U00012356a");
+
+    a = "ab\U00012345c";
+    r = a.dup.reverse;
+    assert(r == "c\U00012345ba");
+}
+
+
+/**********************************************
+ * Support for array.reverse property.
+ */
+
+extern (C) Array _adReverse(Array a, size_t szelem)
+    out (result)
+    {
+        assert(result.ptr is a.ptr);
+    }
+    body
+    {
+        if (a.length >= 2)
+        {
+            byte*    tmp;
+            byte[16] buffer;
+
+            void* lo = a.ptr;
+            void* hi = a.ptr + (a.length - 1) * szelem;
+
+            tmp = buffer.ptr;
+            if (szelem > 16)
+            {
+                //version (Win32)
+                    //tmp = cast(byte*) alloca(szelem);
+                //else
+                    tmp = cast(byte*) gc_malloc(szelem);
+            }
+
+            for (; lo < hi; lo += szelem, hi -= szelem)
+            {
+                memcpy(tmp, lo,  szelem);
+                memcpy(lo,  hi,  szelem);
+                memcpy(hi,  tmp, szelem);
+            }
+
+            version (Win32)
+            {
+            }
+            else
+            {
+                //if (szelem > 16)
+                    // BUG: bad code is generate for delete pointer, tries
+                    // to call delclass.
+                    //gc_free(tmp);
+            }
+        }
+        return Array(a.length, a.ptr);
+    }
+
+unittest
+{
+    debug(adi) printf("array.reverse.unittest\n");
+
+    int[] a = new int[5];
+    int[] b;
+    size_t i;
+
+    for (i = 0; i < 5; i++)
+        a[i] = i;
+    b = a.reverse;
+    assert(b is a);
+    for (i = 0; i < 5; i++)
+        assert(a[i] == 4 - i);
+
+    struct X20
+    {   // More than 16 bytes in size
+        int a;
+        int b, c, d, e;
+    }
+
+    X20[] c = new X20[5];
+    X20[] d;
+
+    for (i = 0; i < 5; i++)
+    {   c[i].a = i;
+        c[i].e = 10;
+    }
+    d = c.reverse;
+    assert(d is c);
+    for (i = 0; i < 5; i++)
+    {
+        assert(c[i].a == 4 - i);
+        assert(c[i].e == 10);
+    }
+}
+
+/**********************************************
+ * Sort array of chars.
+ */
+
+extern (C) Array _adSortChar(char[] a)
+{
+    if (a.length > 1)
+    {
+	dchar[] da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   char[4] buf;
+            auto t = toUTF8(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return Array(a.length, a.ptr);
+}
+
+/**********************************************
+ * Sort array of wchars.
+ */
+
+extern (C) Array _adSortWchar(wchar[] a)
+{
+    if (a.length > 1)
+    {
+	dchar[] da = toUTF32(a);
+        da.sort;
+        size_t i = 0;
+        foreach (dchar d; da)
+        {   wchar[2] buf;
+	    auto t = toUTF16(buf, d);
+            a[i .. i + t.length] = t[];
+            i += t.length;
+        }
+        delete da;
+    }
+    return Array(a.length, a.ptr);
+}
+
+/***************************************
+ * Support for array equality test.
+ */
+
+extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
+
+    if (a1.length != a2.length)
+        return 0;               // not equal
+    else if (a1.ptr == a2.ptr)
+        return 1;               // equal
+
+    // let typeinfo decide
+    return ti.equals(&a1, &a2);
+}
+
+unittest
+{
+    debug(adi) printf("array.Eq unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a != "hel");
+    assert(a != "helloo");
+    assert(a != "betty");
+    assert(a == "hello");
+    assert(a != "hxxxx");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
+{
+    debug(adi) printf("adCmp()\n");
+
+    if (a1.ptr == a2.ptr &&
+        a1.length == a2.length)
+        return 0;
+
+    auto len = a1.length;
+    if (a2.length < len)
+        len = a2.length;
+
+    // let typeinfo decide
+    return ti.compare(&a1, &a2);
+}
+
+unittest
+{
+    debug(adi) printf("array.Cmp unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
+
+/***************************************
+ * Support for array compare test.
+ */
+
+extern (C) int _adCmpChar(Array a1, Array a2)
+{
+  version(D_InlineAsm_X86)
+  {
+  //version = Asm86;
+  }
+  version (Asm86)
+  {
+    asm
+    {   naked                   ;
+
+        push    EDI             ;
+        push    ESI             ;
+
+        mov    ESI,a1+4[4+ESP]  ;
+        mov    EDI,a2+4[4+ESP]  ;
+
+        mov    ECX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        cmp     ECX,EDX         ;
+        jb      GotLength       ;
+
+        mov     ECX,EDX         ;
+
+GotLength:
+        cmp    ECX,4            ;
+        jb    DoBytes           ;
+
+        // Do alignment if neither is dword aligned
+        test    ESI,3           ;
+        jz    Aligned           ;
+
+        test    EDI,3           ;
+        jz    Aligned           ;
+DoAlign:
+        mov    AL,[ESI]         ; //align ESI to dword bounds
+        mov    DL,[EDI]         ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        inc    ESI              ;
+        inc    EDI              ;
+
+        test    ESI,3           ;
+
+        lea    ECX,[ECX-1]      ;
+        jnz    DoAlign          ;
+Aligned:
+        mov    EAX,ECX          ;
+
+        // do multiple of 4 bytes at a time
+
+        shr    ECX,2            ;
+        jz    TryOdd            ;
+
+        repe                    ;
+        cmpsd                   ;
+
+        jnz    UnequalQuad      ;
+
+TryOdd:
+        mov    ECX,EAX          ;
+DoBytes:
+        // if still equal and not end of string, do up to 3 bytes slightly
+        // slower.
+
+        and    ECX,3            ;
+        jz    Equal             ;
+
+        repe                    ;
+        cmpsb                   ;
+
+        jnz    Unequal          ;
+Equal:
+        mov    EAX,a1[4+ESP]    ;
+        mov    EDX,a2[4+ESP]    ;
+
+        sub    EAX,EDX          ;
+        pop    ESI              ;
+
+        pop    EDI              ;
+        ret                     ;
+
+UnequalQuad:
+        mov    EDX,[EDI-4]      ;
+        mov    EAX,[ESI-4]      ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+        jnz    Unequal          ;
+
+        shr    EAX,16           ;
+
+        shr    EDX,16           ;
+
+        cmp    AL,DL            ;
+        jnz    Unequal          ;
+
+        cmp    AH,DH            ;
+Unequal:
+        sbb    EAX,EAX          ;
+        pop    ESI              ;
+
+        or     EAX,1            ;
+        pop    EDI              ;
+
+        ret                     ;
+    }
+  }
+  else
+  {
+    int len;
+    int c;
+
+    debug(adi) printf("adCmpChar()\n");
+    len = cast(int)a1.length;
+    if (a2.length < len)
+        len = cast(int)a2.length;
+    c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
+    if (!c)
+        c = cast(int)a1.length - cast(int)a2.length;
+    return c;
+  }
+}
+
+unittest
+{
+    debug(adi) printf("array.CmpChar unittest\n");
+
+    auto a = "hello"c;
+
+    assert(a >  "hel");
+    assert(a >= "hel");
+    assert(a <  "helloo");
+    assert(a <= "helloo");
+    assert(a >  "betty");
+    assert(a >= "betty");
+    assert(a == "hello");
+    assert(a <= "hello");
+    assert(a >= "hello");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/arrayInit.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,107 @@
+private import llvmdc.intrinsics;
+
+extern(C):
+
+int memcmp(void*,void*,size_t);
+size_t strlen(char*);
+
+version(LLVM64)
+alias llvm_memcpy_i64 llvm_memcpy;
+else
+alias llvm_memcpy_i32 llvm_memcpy;
+
+// per-element array init routines
+
+void _d_array_init_i1(bool* a, size_t n, bool v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_i8(ubyte* a, size_t n, ubyte v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_i16(ushort* a, size_t n, ushort v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_i32(uint* a, size_t n, uint v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_i64(ulong* a, size_t n, ulong v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_float(float* a, size_t n, float v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_double(double* a, size_t n, double v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_real(real* a, size_t n, real v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_pointer(void** a, size_t n, void* v)
+{
+    auto p = a;
+    auto end = a+n;
+    while (p !is end)
+        *p++ = v;
+}
+
+void _d_array_init_mem(void* a, size_t na, void* v, size_t nv)
+{
+    auto p = a;
+    auto end = a + na*nv;
+    while (p !is end) {
+        llvm_memcpy(p,v,nv,0);
+        p += nv;
+    }
+}
+
+// for array cast
+size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
+{
+    if (newelemsz == 1) {
+        return len*elemsz;
+    }
+    else if (len % newelemsz) {
+        throw new Exception("Bad array cast");
+    }
+    return (len*elemsz)/newelemsz;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/cast.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,196 @@
+/*
+ *  Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+extern (C):
+
+//debug = PRINTF;
+debug(PRINTF) int printf(char*, ...);
+
+/******************************************
+ * Given a pointer:
+ *      If it is an Object, return that Object.
+ *      If it is an interface, return the Object implementing the interface.
+ *      If it is null, return null.
+ *      Else, undefined crash
+ */
+
+Object _d_toObject(void* p)
+{   Object o;
+    debug(PRINTF) printf("toObject(%p)\n", p);
+    if (p)
+    {
+        o = cast(Object)p;
+        debug(PRINTF) printf("o = %p\n", o);
+        debug(PRINTF) printf("o.vtbl = %p\n", *cast(void**)p);
+        ClassInfo oc = o.classinfo;
+        debug(PRINTF) printf("oc = %p\n", oc);
+        Interface *pi = **cast(Interface ***)p;
+        debug(PRINTF) printf("pi = %p\n", pi);
+
+        /* Interface.offset lines up with ClassInfo.name.ptr,
+         * so we rely on pointers never being less than 64K,
+         * and interface vtable offsets never being greater.
+         */
+        if (pi.offset < 0x10000)
+        {
+            debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
+            o = cast(Object)(p - pi.offset);
+        }
+    }
+    debug(PRINTF) printf("toObject = %p\n", o);
+    return o;
+}
+
+
+/*************************************
+ * Attempts to cast Object o to class c.
+ * Returns o if successful, null if not.
+ */
+
+Object _d_interface_cast(void* p, ClassInfo c)
+{   Object o;
+
+    debug(PRINTF) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name.length, c.name.ptr);
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+
+        debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
+        o = cast(Object)(p - pi.offset);
+        return _d_dynamic_cast(o, c);
+    }
+    debug(PRINTF) printf("_d_interface_cast = %p\n", o);
+    return o;
+}
+
+Object _d_dynamic_cast(Object o, ClassInfo c)
+{   ClassInfo oc;
+    size_t offset = 0;
+
+    debug(PRINTF) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name.length, c.name.ptr);
+
+    if (o)
+    {
+        oc = o.classinfo;
+        if (_d_isbaseof2(oc, c, offset))
+        {
+            debug(PRINTF) printf("\toffset = %d\n", offset);
+            o = cast(Object)(cast(void*)o + offset);
+        }
+        else
+            o = null;
+    }
+    //printf("\tresult = %p\n", o);
+    debug(PRINTF) printf("_d_dynamic_cast = %p\n", o);
+    return o;
+}
+
+int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
+{   int i;
+
+    debug(PRINTF) printf("_d_isbaseof2(%.*s, %.*s, %ul)\n", oc.name.length, oc.name.ptr, c.name.length, c.name.ptr, offset);
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        debug(PRINTF) printf("oc.interfaces.length = %ul\n", oc.interfaces.length);
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            debug(PRINTF) printf("checking %.*s\n", ic.name.length, ic.name.ptr);
+            if (ic is c)
+            {   offset = cast(size_t)oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (_d_isbaseof2(ic, c, offset))
+            {   offset = cast(size_t)oc.interfaces[i].offset;
+                return 1;
+            }
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+int _d_isbaseof(ClassInfo oc, ClassInfo c)
+{   int i;
+
+    if (oc is c)
+        return 1;
+    do
+    {
+        if (oc.base is c)
+            return 1;
+        for (i = 0; i < oc.interfaces.length; i++)
+        {
+            ClassInfo ic;
+
+            ic = oc.interfaces[i].classinfo;
+            if (ic is c || _d_isbaseof(ic, c))
+                return 1;
+        }
+        oc = oc.base;
+    } while (oc);
+    return 0;
+}
+
+/*********************************
+ * Find the vtbl[] associated with Interface ic.
+ */
+
+void *_d_interface_vtbl(ClassInfo ic, Object o)
+{   int i;
+    ClassInfo oc;
+
+    //printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
+
+    assert(o);
+
+    oc = o.classinfo;
+    for (i = 0; i < oc.interfaces.length; i++)
+    {
+        ClassInfo oic;
+
+        oic = oc.interfaces[i].classinfo;
+        if (oic is ic)
+        {
+            return cast(void *)oc.interfaces[i].vtbl;
+        }
+    }
+    assert(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/critical.c	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,160 @@
+/*
+ * Placed into the Public Domain
+ * written by Walter Bright, Digital Mars
+ * www.digitalmars.com
+ */
+
+/* ================================= Win32 ============================ */
+
+#if _WIN32
+
+#include	<windows.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    CRITICAL_SECTION cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static volatile int inited;
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs->next)
+    {
+	EnterCriticalSection(&critical_section.cs);
+	if (!dcs->next)	// if, in the meantime, another thread didn't set it
+	{
+	    dcs->next = dcs_list;
+	    dcs_list = dcs;
+	    InitializeCriticalSection(&dcs->cs);
+	}
+	LeaveCriticalSection(&critical_section.cs);
+    }
+    EnterCriticalSection(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    LeaveCriticalSection(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!inited)
+    {	InitializeCriticalSection(&critical_section.cs);
+	dcs_list = &critical_section;
+	inited = 1;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (inited)
+    {	inited = 0;
+	while (dcs_list)
+	{
+	    DeleteCriticalSection(&dcs_list->cs);
+	    dcs_list = dcs_list->next;
+	}
+    }
+}
+
+#endif
+
+/* ================================= linux ============================ */
+
+#if linux
+
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<pthread.h>
+
+/******************************************
+ * Enter/exit critical section.
+ */
+
+/* We don't initialize critical sections unless we actually need them.
+ * So keep a linked list of the ones we do use, and in the static destructor
+ * code, walk the list and release them.
+ */
+
+typedef struct D_CRITICAL_SECTION
+{
+    struct D_CRITICAL_SECTION *next;
+    pthread_mutex_t cs;
+} D_CRITICAL_SECTION;
+
+static D_CRITICAL_SECTION *dcs_list;
+static D_CRITICAL_SECTION critical_section;
+static pthread_mutexattr_t _criticals_attr;
+
+void _STI_critical_init(void);
+void _STD_critical_term(void);
+
+void _d_criticalenter(D_CRITICAL_SECTION *dcs)
+{
+    if (!dcs_list)
+    {	_STI_critical_init();
+	atexit(_STD_critical_term);
+    }
+    //printf("_d_criticalenter(dcs = x%x)\n", dcs);
+    if (!dcs->next)
+    {
+	pthread_mutex_lock(&critical_section.cs);
+	if (!dcs->next)	// if, in the meantime, another thread didn't set it
+	{
+	    dcs->next = dcs_list;
+	    dcs_list = dcs;
+	    pthread_mutex_init(&dcs->cs, &_criticals_attr);
+	}
+	pthread_mutex_unlock(&critical_section.cs);
+    }
+    pthread_mutex_lock(&dcs->cs);
+}
+
+void _d_criticalexit(D_CRITICAL_SECTION *dcs)
+{
+    //printf("_d_criticalexit(dcs = x%x)\n", dcs);
+    pthread_mutex_unlock(&dcs->cs);
+}
+
+void _STI_critical_init()
+{
+    if (!dcs_list)
+    {	//printf("_STI_critical_init()\n");
+	pthread_mutexattr_init(&_criticals_attr);
+	pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+
+	// The global critical section doesn't need to be recursive
+	pthread_mutex_init(&critical_section.cs, 0);
+	dcs_list = &critical_section;
+    }
+}
+
+void _STD_critical_term()
+{
+    if (dcs_list)
+    {	//printf("_STI_critical_term()\n");
+	while (dcs_list)
+	{
+	    //printf("\tlooping... %x\n", dcs_list);
+	    pthread_mutex_destroy(&dcs_list->cs);
+	    dcs_list = dcs_list->next;
+	}
+    }
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/dmain2.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,293 @@
+/*
+ * Placed into the Public Domain.
+ * written by Walter Bright
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+private
+{
+    import util.console;
+
+    import tango.stdc.stddef;
+    import tango.stdc.stdlib;
+    import tango.stdc.string;
+}
+
+version( Win32 )
+{
+    extern (Windows) void*      LocalFree(void*);
+    extern (Windows) wchar_t*   GetCommandLineW();
+    extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
+    extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
+    //pragma(lib, "shell32.lib");   // needed for CommandLineToArgvW
+    //pragma(lib, "tango-win32-dmd.lib"); // links Tango's Win32 library to reduce EXE size
+}
+
+extern (C) void _STI_monitor_staticctor();
+extern (C) void _STD_monitor_staticdtor();
+extern (C) void _STI_critical_init();
+extern (C) void _STD_critical_term();
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+//debug=PRINTF;
+debug(PRINTF) extern (C) int printf(char*, ...);
+
+/***********************************
+ * These functions must be defined for any D program linked
+ * against this library.
+ */
+extern (C) void onAssertError( char[] file, size_t line );
+extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg );
+extern (C) void onArrayBoundsError( char[] file, size_t line );
+extern (C) void onSwitchError( char[] file, size_t line );
+extern (C) bool runModuleUnitTests();
+
+// this function is called from the utf module
+//extern (C) void onUnicodeError( char[] msg, size_t idx );
+
+/***********************************
+ * These are internal callbacks for various language errors.
+ */
+extern (C) void _d_assert( char[] file, uint line )
+{
+    onAssertError( file, line );
+}
+
+extern (C) void _d_assert_msg( char[] msg, char[] file, uint line )
+{
+    onAssertErrorMsg( file, line, msg );
+}
+
+extern (C) void _d_array_bounds( char[] file, uint line )
+{
+    onArrayBoundsError( file, line );
+}
+
+extern (C) void _d_switch_error( char[] file, uint line )
+{
+    onSwitchError( file, line );
+}
+
+bool _d_isHalting = false;
+
+extern (C) bool rt_isHalting()
+{
+    return _d_isHalting;
+}
+
+extern (C) bool rt_trapExceptions = true;
+
+void _d_criticalInit()
+{
+    _STI_monitor_staticctor();
+    _STI_critical_init();
+}
+
+alias void delegate( Exception ) ExceptionHandler;
+
+// this is here so users can manually initialize the runtime
+// for example, when there is no main function etc.
+extern (C) bool rt_init( ExceptionHandler dg = null )
+{
+    _d_criticalInit();
+
+    try
+    {
+        gc_init();
+        _moduleCtor();
+        return true;
+    }
+    catch( Exception e )
+    {
+        if( dg )
+            dg( e );
+    }
+    catch
+    {
+
+    }
+    _d_criticalTerm();
+    return false;
+}
+
+void _d_criticalTerm()
+{
+    _STD_critical_term();
+    _STD_monitor_staticdtor();
+}
+
+// this is here so users can manually terminate the runtime
+// for example, when there is no main function etc.
+extern (C) bool rt_term( ExceptionHandler dg = null )
+{
+    try
+    {
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+        return true;
+    }
+    catch( Exception e )
+    {
+        if( dg )
+            dg( e );
+    }
+    catch
+    {
+
+    }
+    finally
+    {
+        _d_criticalTerm();
+    }
+    return false;
+}
+
+/***********************************
+ * The D main() function supplied by the user's program
+ */
+int main(char[][] args);
+
+/***********************************
+ * Substitutes for the C main() function.
+ * It's purpose is to wrap the call to the D main()
+ * function and catch any unhandled exceptions.
+ */
+
+extern (C) int main(int argc, char **argv, char** env)
+{
+    char[][] args;
+    int result;
+
+    debug(PRINTF) printf("main ctors\n");
+    _STI_monitor_staticctor();
+    _STI_critical_init();
+
+    debug(PRINTF) printf("main args\n");
+    version (Win32)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen( wargs[i] );
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
+        }
+        LocalFree(wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (linux)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+    debug(PRINTF) printf("main trap exceptions\n");
+    bool trapExceptions = rt_trapExceptions;
+
+    void tryExec(void delegate() dg)
+    {
+        debug(PRINTF) printf("main try exec\n");
+        if (trapExceptions)
+        {
+            try
+            {
+                dg();
+            }
+            catch (Exception e)
+            {
+                while (e)
+                {
+                    if (e.file)
+                    {
+                       debug(PRINTF) printf("%.*s(%u): %.*s\n", e.file.length, e.file.ptr, e.line, e.msg.length, e.msg.ptr);
+                       console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
+                    }
+                    else
+                    {
+                       // debug(PRINTF) printf("%.*s\n", e.toString());
+                       console (e.classinfo.name)(": ")(e.toString)("\n");
+                    }
+                    e = e.next;
+                }
+                result = EXIT_FAILURE;
+            }
+            catch (Object o)
+            {
+                // fprintf(stderr, "%.*s\n", o.toString());
+                console (o.toString)("\n");
+                result = EXIT_FAILURE;
+            }
+        }
+        else
+        {
+            dg();
+        }
+    }
+
+    // NOTE: The lifetime of a process is much like the lifetime of an object:
+    //       it is initialized, then used, then destroyed.  If initialization
+    //       fails, the successive two steps are never reached.  However, if
+    //       initialization succeeds, then cleanup will occur even if the use
+    //       step fails in some way.  Here, the use phase consists of running
+    //       the user's main function.  If main terminates with an exception,
+    //       the exception is handled and then cleanup begins.  An exception
+    //       thrown during cleanup, however, will abort the cleanup process.
+
+    void runMain()
+    {
+        debug(PRINTF) printf("main runMain\n");
+        result = main(args);
+    }
+
+    void runAll()
+    {
+        debug(PRINTF) printf("main runAll\n");
+        gc_init();
+        _moduleCtor();
+        if (runModuleUnitTests())
+            tryExec(&runMain);
+        thread_joinAll();
+        _d_isHalting = true;
+        _moduleDtor();
+        gc_term();
+    }
+
+    tryExec(&runAll);
+
+    debug(PRINTF) printf("main dtor\n");
+    _STD_critical_term();
+    _STD_monitor_staticdtor();
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/eh.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,356 @@
+/**
+ * This module contains functions and structures required for
+ * exception handling.
+ */
+module eh;
+
+import util.console;
+
+// debug = EH_personality;
+
+// current EH implementation works on x86 linux only
+version(X86) version(linux) version=X86_LINUX;
+
+private extern(C) void abort();
+private extern(C) int printf(char*, ...);
+
+// D runtime functions
+extern(C) {
+    int _d_isbaseof(ClassInfo oc, ClassInfo c);
+}
+
+// libunwind headers
+extern(C)
+{
+    enum _Unwind_Reason_Code
+    {
+        NO_REASON = 0,
+        FOREIGN_EXCEPTION_CAUGHT = 1,
+        FATAL_PHASE2_ERROR = 2,
+        FATAL_PHASE1_ERROR = 3,
+        NORMAL_STOP = 4,
+        END_OF_STACK = 5,
+        HANDLER_FOUND = 6,
+        INSTALL_CONTEXT = 7,
+        CONTINUE_UNWIND = 8
+    }
+
+    enum _Unwind_Action
+    {
+        SEARCH_PHASE = 1,
+        CLEANUP_PHASE = 2,
+        HANDLER_PHASE = 3,
+        FORCE_UNWIND = 4
+    }
+
+    alias void* _Unwind_Context_Ptr;
+
+    alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn;
+
+    struct _Unwind_Exception
+    {
+        char[8] exception_class;
+        _Unwind_Exception_Cleanup_Fn exception_cleanup;
+        int private_1;
+        int private_2;
+    }
+
+version(X86_LINUX) 
+{
+    void _Unwind_Resume(_Unwind_Exception*);
+    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
+    ulong _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
+    ulong _Unwind_GetIP(_Unwind_Context_Ptr context);
+    ulong _Unwind_SetIP(_Unwind_Context_Ptr context, ulong new_value);
+    ulong _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ulong new_value);
+    ulong _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
+}
+else
+{
+    // runtime calls these directly
+    void _Unwind_Resume(_Unwind_Exception*)
+    {
+        console("_Unwind_Resume is not implemented on this platform.\n");
+    }
+    _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
+    {
+        console("_Unwind_RaiseException is not implemented on this platform.\n");
+        return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+    }
+}
+
+}
+
+
+// helpers for reading certain DWARF data
+//TODO: It may not be a good idea to use exceptions for error handling within exception handling code
+private ubyte* get_uleb128(ubyte* addr, ref size_t res)
+{
+  res = 0;
+  size_t bitsize = 0;
+
+  // read as long as high bit is set
+  while(*addr & 0x80) {
+    res |= (*addr & 0x7f) << bitsize;
+    bitsize += 7;
+    addr += 1;
+    if(bitsize >= size_t.sizeof*8)
+       throw new Exception("tried to read uleb128 that exceeded size of size_t");
+  }
+  // read last
+  if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
+    throw new Exception("tried to read uleb128 that exceeded size of size_t");
+  res |= (*addr) << bitsize;
+
+  return addr + 1;
+}
+
+private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
+{
+  res = 0;
+  size_t bitsize = 0;
+
+  // read as long as high bit is set
+  while(*addr & 0x80) {
+    res |= (*addr & 0x7f) << bitsize;
+    bitsize += 7;
+    addr += 1;
+    if(bitsize >= size_t.sizeof*8)
+       throw new Exception("tried to read sleb128 that exceeded size of size_t");
+  }
+  // read last
+  if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
+    throw new Exception("tried to read sleb128 that exceeded size of size_t");
+  res |= (*addr) << bitsize;
+
+  // take care of sign
+  if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
+    res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
+
+  return addr + 1;
+}
+
+
+// exception struct used by the runtime.
+// _d_throw allocates a new instance and passes the address of its
+// _Unwind_Exception member to the unwind call. The personality
+// routine is then able to get the whole struct by looking at the data
+// surrounding the unwind info.
+struct _d_exception
+{
+  Object exception_object;
+  _Unwind_Exception unwind_info;
+}
+
+// the 8-byte string identifying the type of exception
+// the first 4 are for vendor, the second 4 for language
+//TODO: This may be the wrong way around
+char[8] _d_exception_class = "LLDCD1\0\0";
+
+
+//
+// x86 Linux specific implementation of personality function
+// and helpers
+//
+version(X86_LINUX) 
+{
+
+// the personality routine gets called by the unwind handler and is responsible for
+// reading the EH tables and deciding what to do
+extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
+{
+  // check ver: the C++ Itanium ABI only allows ver == 1
+  if(ver != 1)
+    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+
+  // check exceptionClass
+  //TODO: Treat foreign exceptions with more respect
+  if((cast(char*)&exception_class)[0..8] != _d_exception_class)
+    return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
+
+  // find call site table, action table and classinfo table
+  // Note: callsite and action tables do not contain static-length
+  // data and will be parsed as needed
+  // Note: classinfo_table points past the end of the table
+  ubyte* callsite_table;
+  ubyte* action_table;
+  ClassInfo* classinfo_table;
+  _d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
+
+
+  /*
+    find landing pad and action table index belonging to ip by walking
+    the callsite_table
+  */
+  ubyte* callsite_walker = callsite_table;
+
+  // get the instruction pointer
+  // will be used to find the right entry in the callsite_table
+  // -1 because it will point past the last instruction
+  ulong ip = _Unwind_GetIP(context) - 1;
+
+  // address block_start is relative to
+  ulong region_start = _Unwind_GetRegionStart(context);
+
+  // table entries
+  uint block_start_offset, block_size;
+  ulong landing_pad;
+  size_t action_offset;
+
+  while(true) {
+    // if we've gone through the list and found nothing...
+    if(callsite_walker >= action_table)
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+
+    block_start_offset = *cast(uint*)callsite_walker;
+    block_size = *(cast(uint*)callsite_walker + 1);
+    landing_pad = *(cast(uint*)callsite_walker + 2);
+    if(landing_pad)
+      landing_pad += region_start;
+    callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
+
+    debug(EH_personality_verbose) printf("%d %d %d\n", block_start_offset, block_size, landing_pad);
+
+    // since the list is sorted, as soon as we're past the ip
+    // there's no handler to be found
+    if(ip < region_start + block_start_offset)
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+
+    // if we've found our block, exit
+    if(ip < region_start + block_start_offset + block_size)
+      break;
+  }
+
+  debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);
+
+  // now we need the exception's classinfo to find a handler
+  // the exception_info is actually a member of a larger _d_exception struct
+  // the runtime allocated. get that now
+  _d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
+
+  // if there's no action offset and no landing pad, continue unwinding
+  if(!action_offset && !landing_pad)
+    return _Unwind_Reason_Code.CONTINUE_UNWIND;
+
+  // if there's no action offset but a landing pad, this is a cleanup handler
+  else if(!action_offset && landing_pad)
+    return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
+
+  /*
+   walk action table chain, comparing classinfos using _d_isbaseof
+  */
+  ubyte* action_walker = action_table + action_offset - 1;
+
+  ptrdiff_t ti_offset, next_action_offset;
+  while(true) {
+    action_walker = get_sleb128(action_walker, ti_offset);
+    // it is intentional that we not modify action_walker here
+    // next_action_offset is from current action_walker position
+    get_sleb128(action_walker, next_action_offset);
+
+    // negative are 'filters' which we don't use
+    assert(ti_offset >= 0 && "Filter actions are unsupported");
+
+    // zero means cleanup, which we require to be the last action
+    if(ti_offset == 0) {
+      assert(next_action_offset == 0 && "Cleanup action must be last in chain");
+      return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
+    }
+
+    // get classinfo for action and check if the one in the
+    // exception structure is a base
+    ClassInfo catch_ci = classinfo_table[-ti_offset];
+    debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
+    if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci))
+      return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
+
+    // we've walked through all actions and found nothing...
+    if(next_action_offset == 0)
+      return _Unwind_Reason_Code.CONTINUE_UNWIND;
+    else
+      action_walker += next_action_offset;
+  }
+
+  assert(false);
+}
+
+// These are the register numbers for SetGR that
+// llvm's eh.exception and eh.selector intrinsics
+// will pick up.
+// Found by trial-and-error and probably platform dependent!
+private int eh_exception_regno = 0;
+private int eh_selector_regno = 2;
+
+private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
+{
+  debug(EH_personality) printf("Found catch clause!\n");
+
+  if(actions & _Unwind_Action.SEARCH_PHASE)
+    return _Unwind_Reason_Code.HANDLER_FOUND;
+
+  else if(actions & _Unwind_Action.HANDLER_PHASE)
+  {
+    debug(EH_personality) printf("Setting switch value to: %d!\n", switchval);
+    _Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
+    _Unwind_SetGR(context, eh_selector_regno, switchval);
+    _Unwind_SetIP(context, landing_pad);
+    return _Unwind_Reason_Code.INSTALL_CONTEXT;
+  }
+
+  assert(false);
+}
+
+private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
+{
+  // if we're merely in search phase, continue
+  if(actions & _Unwind_Action.SEARCH_PHASE)
+    return _Unwind_Reason_Code.CONTINUE_UNWIND;
+
+  debug(EH_personality) printf("Calling cleanup routine...\n");
+
+  _Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
+  _Unwind_SetGR(context, eh_selector_regno, 0);
+  _Unwind_SetIP(context, landing_pad);
+  return _Unwind_Reason_Code.INSTALL_CONTEXT;
+}
+
+private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
+{
+  ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
+
+  //TODO: Do proper DWARF reading here
+  assert(*data++ == 0xff);
+
+  assert(*data++ == 0x00);
+  size_t cioffset;
+  data = get_uleb128(data, cioffset);
+  ci = cast(ClassInfo*)(data + cioffset);
+
+  assert(*data++ == 0x03);
+  size_t callsitelength;
+  data = get_uleb128(data, callsitelength);
+  action = data + callsitelength;
+
+  callsite = data;
+}
+
+} // end of x86 Linux specific implementation
+
+
+extern(C) void _d_throw_exception(Object e)
+{
+    if (e !is null)
+    {
+        _d_exception* exc_struct = new _d_exception;
+        exc_struct.unwind_info.exception_class[] = _d_exception_class;
+        exc_struct.exception_object = e;
+        _Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
+        console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
+    }
+    abort();
+}
+
+extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
+{
+  _Unwind_Resume(&exception_struct.unwind_info);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/genobj.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,1294 @@
+/**
+ * Part of the D programming language runtime library.
+ * Forms the symbols available to all D programs. Includes
+ * Object, which is the root of the class object hierarchy.
+ *
+ * This module is implicitly imported.
+ * Macros:
+ *      WIKI = Object
+ */
+
+/*
+ *  Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ *  Modified by Tomas Lindquist Olsen <tomas@famolsen.dk> for use with LLVMDC.
+ */
+
+module object;
+
+//debug=PRINTF
+
+private
+{
+    import tango.stdc.string; // : memcmp, memcpy, memmove;
+    import tango.stdc.stdlib; // : calloc, realloc, free;
+    import util.string;
+    debug(PRINTF) import tango.stdc.stdio; // : printf;
+
+    extern (C) void onOutOfMemoryError();
+    extern (C) Object _d_newclass(ClassInfo ci);
+}
+
+// NOTE: For some reason, this declaration method doesn't work
+//       in this particular file (and this file only).  It must
+//       be a DMD thing.
+//alias typeof(int.sizeof)                    size_t;
+//alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
+
+version( LLVM64 )
+{
+    alias ulong size_t;
+    alias long  ptrdiff_t;
+}
+else
+{
+    alias uint  size_t;
+    alias int   ptrdiff_t;
+}
+
+alias size_t hash_t;
+
+/**
+ * All D class objects inherit from Object.
+ */
+class Object
+{
+    /**
+     * Convert Object to a human readable string.
+     */
+    char[] toString()
+    {
+        return this.classinfo.name;
+    }
+
+    /**
+     * Compute hash function for Object.
+     */
+    hash_t toHash()
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        return cast(hash_t)cast(void*)this;
+    }
+
+    /**
+     * Compare with another Object obj.
+     * Returns:
+     *  $(TABLE
+     *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
+     *  $(TR $(TD this == obj) $(TD 0))
+     *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
+     *  )
+     */
+    int opCmp(Object o)
+    {
+        // BUG: this prevents a compacting GC from working, needs to be fixed
+        //return cast(int)cast(void*)this - cast(int)cast(void*)o;
+
+        //throw new Exception("need opCmp for class " ~ this.classinfo.name);
+        return this !is o;
+    }
+
+    /**
+     * Returns !=0 if this object does have the same contents as obj.
+     */
+    int opEquals(Object o)
+    {
+        return cast(int)(this is o);
+    }
+
+    interface Monitor
+    {
+        void lock();
+        void unlock();
+    }
+}
+
+/**
+ * Information about an interface.
+ * When an object is accessed via an interface, an Interface* appears as the
+ * first entry in its vtbl.
+ */
+struct Interface
+{
+    ClassInfo   classinfo;  /// .classinfo for this interface (not for containing class)
+    void*[]     vtbl;
+    ptrdiff_t   offset;     /// offset to Interface 'this' from Object 'this'
+}
+
+/**
+ * Runtime type information about a class. Can be retrieved for any class type
+ * or instance by using the .classinfo property.
+ * A pointer to this appears as the first entry in the class's vtbl[].
+ */
+class ClassInfo : Object
+{
+    byte[]      init;           /** class static initializer
+                                 * (init.length gives size in bytes of class)
+                                 */
+    char[]      name;           /// class name
+    void*[]     vtbl;           /// virtual function pointer table
+    Interface[] interfaces;     /// interfaces this class implements
+    ClassInfo   base;           /// base class
+    void*       destructor;
+    void function(Object) classInvariant;
+    uint        flags;
+    //  1:                      // IUnknown
+    //  2:                      // has no possible pointers into GC memory
+    //  4:                      // has offTi[] member
+    //  8:                      // has constructors
+    void*       deallocator;
+    OffsetTypeInfo[] offTi;
+    void function(Object) defaultConstructor;   // default Constructor
+
+    /**
+     * Search all modules for ClassInfo corresponding to classname.
+     * Returns: null if not found
+     */
+    static ClassInfo find(char[] classname)
+    {
+        foreach (m; ModuleInfo)
+        {
+            //writefln("module %s, %d", m.name, m.localClasses.length);
+            foreach (c; m.localClasses)
+            {
+                //writefln("\tclass %s", c.name);
+                if (c.name == classname)
+                    return c;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Create instance of Object represented by 'this'.
+     */
+    Object create()
+    {
+        if (flags & 8 && !defaultConstructor)
+            return null;
+        Object o = _d_newclass(this);
+        if (flags & 8 && defaultConstructor)
+        {
+            defaultConstructor(o);
+        }
+        return o;
+    }
+}
+
+/**
+ * Array of pairs giving the offset and type information for each
+ * member in an aggregate.
+ */
+struct OffsetTypeInfo
+{
+    size_t   offset;    /// Offset of member from start of object
+    TypeInfo ti;        /// TypeInfo for this member
+}
+
+/**
+ * Runtime type information about a type.
+ * Can be retrieved for any type using a
+ * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
+ */
+class TypeInfo
+{
+    hash_t toHash()
+    {   hash_t hash;
+
+        foreach (char c; this.toString())
+            hash = hash * 9 + c;
+        return hash;
+    }
+
+    int opCmp(Object o)
+    {
+        if (this is o)
+            return 0;
+        TypeInfo ti = cast(TypeInfo)o;
+        if (ti is null)
+            return 1;
+        return stringCompare(this.toString(), ti.toString());
+    }
+
+    int opEquals(Object o)
+    {
+        /* TypeInfo instances are singletons, but duplicates can exist
+         * across DLL's. Therefore, comparing for a name match is
+         * sufficient.
+         */
+        if (this is o)
+            return 1;
+        TypeInfo ti = cast(TypeInfo)o;
+        return cast(int)(ti && this.toString() == ti.toString());
+    }
+
+    /// Returns a hash of the instance of a type.
+    hash_t getHash(void *p) { return cast(hash_t)p; }
+
+    /// Compares two instances for equality.
+    int equals(void *p1, void *p2) { return cast(int)(p1 == p2); }
+
+    /// Compares two instances for &lt;, ==, or &gt;.
+    int compare(void *p1, void *p2) { return 0; }
+
+    /// Returns size of the type.
+    size_t tsize() { return 0; }
+
+    /// Swaps two instances of the type.
+    void swap(void *p1, void *p2)
+    {
+        size_t n = tsize();
+        for (size_t i = 0; i < n; i++)
+        {   byte t;
+
+            t = (cast(byte *)p1)[i];
+            (cast(byte *)p1)[i] = (cast(byte *)p2)[i];
+            (cast(byte *)p2)[i] = t;
+        }
+    }
+
+    /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
+    /// null if none.
+    TypeInfo next() { return null; }
+
+    /// Return default initializer, null if default initialize to 0
+    void[] init() { return null; }
+
+    /// Get flags for type: 1 means GC should scan for pointers
+    uint flags() { return 0; }
+
+    /// Get type information on the contents of the type; null if not available
+    OffsetTypeInfo[] offTi() { return null; }
+}
+
+class TypeInfo_Typedef : TypeInfo
+{
+    char[] toString() { return name; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Typedef c;
+
+        return cast(int)
+                (this is o ||
+                ((c = cast(TypeInfo_Typedef)o) !is null &&
+                 this.name == c.name &&
+                 this.base == c.base));
+    }
+
+    hash_t getHash(void *p) { return base.getHash(p); }
+    int equals(void *p1, void *p2) { return base.equals(p1, p2); }
+    int compare(void *p1, void *p2) { return base.compare(p1, p2); }
+    size_t tsize() { return base.tsize(); }
+    void swap(void *p1, void *p2) { return base.swap(p1, p2); }
+
+    TypeInfo next() { return base; }
+    uint flags() { return base.flags(); }
+    void[] init() { return m_init.length ? m_init : base.init(); }
+
+    TypeInfo base;
+    char[] name;
+    void[] m_init;
+}
+
+class TypeInfo_Enum : TypeInfo_Typedef
+{
+}
+
+class TypeInfo_Pointer : TypeInfo
+{
+    char[] toString() { return m_next.toString() ~ "*"; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Pointer c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_Pointer)o) !is null &&
+                 this.m_next == c.m_next);
+    }
+
+    hash_t getHash(void *p)
+    {
+        return cast(hash_t)*cast(void**)p;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        return cast(int)(*cast(void* *)p1 == *cast(void* *)p2);
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        if (*cast(void* *)p1 < *cast(void* *)p2)
+            return -1;
+        else if (*cast(void* *)p1 > *cast(void* *)p2)
+            return 1;
+        else
+            return 0;
+    }
+
+    size_t tsize()
+    {
+        return (void*).sizeof;
+    }
+
+    void swap(void *p1, void *p2)
+    {   void* tmp;
+        tmp = *cast(void**)p1;
+        *cast(void**)p1 = *cast(void**)p2;
+        *cast(void**)p2 = tmp;
+    }
+
+    TypeInfo next() { return m_next; }
+    uint flags() { return 1; }
+
+    TypeInfo m_next;
+}
+
+class TypeInfo_Array : TypeInfo
+{
+    char[] toString() { return value.toString() ~ "[]"; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Array c;
+
+        return cast(int)
+               (this is o ||
+                ((c = cast(TypeInfo_Array)o) !is null &&
+                 this.value == c.value));
+    }
+
+    hash_t getHash(void *p)
+    {   size_t sz = value.tsize();
+        hash_t hash = 0;
+        void[] a = *cast(void[]*)p;
+        for (size_t i = 0; i < a.length; i++)
+            hash += value.getHash(a.ptr + i * sz);
+        return hash;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        if (a1.length != a2.length)
+            return 0;
+        size_t sz = value.tsize();
+        for (size_t i = 0; i < a1.length; i++)
+        {
+            if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
+                return 0;
+        }
+        return 1;
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        void[] a1 = *cast(void[]*)p1;
+        void[] a2 = *cast(void[]*)p2;
+        size_t sz = value.tsize();
+        size_t len = a1.length;
+
+        if (a2.length < len)
+            len = a2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
+            if (result)
+                return result;
+        }
+        return cast(int)a1.length - cast(int)a2.length;
+    }
+
+    size_t tsize()
+    {
+        return (void[]).sizeof;
+    }
+
+    void swap(void *p1, void *p2)
+    {   void[] tmp;
+        tmp = *cast(void[]*)p1;
+        *cast(void[]*)p1 = *cast(void[]*)p2;
+        *cast(void[]*)p2 = tmp;
+    }
+
+    TypeInfo value;
+
+    TypeInfo next()
+    {
+        return value;
+    }
+
+    uint flags() { return 1; }
+}
+
+class TypeInfo_StaticArray : TypeInfo
+{
+    char[] toString()
+    {
+        char [10] tmp = void;
+        return value.toString() ~ "[" ~ intToUtf8(tmp, len) ~ "]";
+    }
+
+    int opEquals(Object o)
+    {   TypeInfo_StaticArray c;
+
+        return cast(int)
+               (this is o ||
+                ((c = cast(TypeInfo_StaticArray)o) !is null &&
+                 this.len == c.len &&
+                 this.value == c.value));
+    }
+
+    hash_t getHash(void *p)
+    {   size_t sz = value.tsize();
+        hash_t hash = 0;
+        for (size_t i = 0; i < len; i++)
+            hash += value.getHash(p + i * sz);
+        return hash;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            if (!value.equals(p1 + u * sz, p2 + u * sz))
+                return 0;
+        }
+        return 1;
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        size_t sz = value.tsize();
+
+        for (size_t u = 0; u < len; u++)
+        {
+            int result = value.compare(p1 + u * sz, p2 + u * sz);
+            if (result)
+                return result;
+        }
+        return 0;
+    }
+
+    size_t tsize()
+    {
+        return len * value.tsize();
+    }
+
+    void swap(void *p1, void *p2)
+    {   void* tmp;
+        size_t sz = value.tsize();
+        ubyte[16] buffer;
+        void* pbuffer;
+
+        if (sz < buffer.sizeof)
+            tmp = buffer.ptr;
+        else
+            tmp = pbuffer = (new void[sz]).ptr;
+
+        for (size_t u = 0; u < len; u += sz)
+        {   size_t o = u * sz;
+            memcpy(tmp, p1 + o, sz);
+            memcpy(p1 + o, p2 + o, sz);
+            memcpy(p2 + o, tmp, sz);
+        }
+        if (pbuffer)
+            delete pbuffer;
+    }
+
+    void[] init() { return value.init(); }
+    TypeInfo next() { return value; }
+    uint flags() { return value.flags(); }
+
+    TypeInfo value;
+    size_t len;
+}
+
+class TypeInfo_AssociativeArray : TypeInfo
+{
+    char[] toString()
+    {
+        return next.toString() ~ "[" ~ key.toString() ~ "]";
+    }
+
+    int opEquals(Object o)
+    {   TypeInfo_AssociativeArray c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
+                 this.key == c.key &&
+                 this.value == c.value);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    size_t tsize()
+    {
+        return (char[int]).sizeof;
+    }
+
+    TypeInfo next() { return value; }
+    uint flags() { return 1; }
+
+    TypeInfo value;
+    TypeInfo key;
+}
+
+class TypeInfo_Function : TypeInfo
+{
+    char[] toString()
+    {
+        return next.toString() ~ "()";
+    }
+
+    int opEquals(Object o)
+    {   TypeInfo_Function c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_Function)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    size_t tsize()
+    {
+        return 0;       // no size for functions
+    }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Delegate : TypeInfo
+{
+    char[] toString()
+    {
+        return next.toString() ~ " delegate()";
+    }
+
+    int opEquals(Object o)
+    {   TypeInfo_Delegate c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_Delegate)o) !is null &&
+                 this.next == c.next);
+    }
+
+    // BUG: need to add the rest of the functions
+
+    size_t tsize()
+    {   alias int delegate() dg;
+        return dg.sizeof;
+    }
+
+    uint flags() { return 1; }
+
+    TypeInfo next;
+}
+
+class TypeInfo_Class : TypeInfo
+{
+    char[] toString() { return info.name; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Class c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_Class)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    hash_t getHash(void *p)
+    {
+        Object o = *cast(Object*)p;
+        return o ? o.toHash() : 0;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+
+        return (o1 is o2) || (o1 && o1.opEquals(o2));
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        Object o1 = *cast(Object*)p1;
+        Object o2 = *cast(Object*)p2;
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 !is o2)
+        {
+            if (o1)
+            {   if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    uint flags() { return 1; }
+
+    OffsetTypeInfo[] offTi()
+    {
+        return (info.flags & 4) ? info.offTi : null;
+    }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Interface : TypeInfo
+{
+    char[] toString() { return info.name; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Interface c;
+
+        return this is o ||
+                ((c = cast(TypeInfo_Interface)o) !is null &&
+                 this.info.name == c.classinfo.name);
+    }
+
+    hash_t getHash(void *p)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p;
+        Object o = cast(Object)(*cast(void**)p - pi.offset);
+        assert(o);
+        return o.toHash();
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+
+        return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        Interface* pi = **cast(Interface ***)*cast(void**)p1;
+        Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
+        pi = **cast(Interface ***)*cast(void**)p2;
+        Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (o1 != o2)
+        {
+            if (o1)
+            {   if (!o2)
+                    c = 1;
+                else
+                    c = o1.opCmp(o2);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    size_t tsize()
+    {
+        return Object.sizeof;
+    }
+
+    uint flags() { return 1; }
+
+    ClassInfo info;
+}
+
+class TypeInfo_Struct : TypeInfo
+{
+    char[] toString() { return name; }
+
+    int opEquals(Object o)
+    {   TypeInfo_Struct s;
+
+        return this is o ||
+                ((s = cast(TypeInfo_Struct)o) !is null &&
+                 this.name == s.name &&
+                 this.init.length == s.init.length);
+    }
+
+    hash_t getHash(void *p)
+    {   hash_t h;
+
+        assert(p);
+        if (xtoHash)
+        {   debug(PRINTF) printf("getHash() using xtoHash\n");
+            h = (*xtoHash)(p);
+        }
+        else
+        {
+            debug(PRINTF) printf("getHash() using default hash\n");
+            // A sorry hash algorithm.
+            // Should use the one for strings.
+            // BUG: relies on the GC not moving objects
+            for (size_t i = 0; i < m_init.length; i++)
+            {   h = h * 9 + *cast(ubyte*)p;
+                p++;
+            }
+        }
+        return h;
+    }
+
+    int equals(void *p1, void *p2)
+    {   int c;
+
+        if (p1 == p2)
+            c = 1;
+        else if (!p1 || !p2)
+            c = 0;
+        else if (xopEquals)
+            c = (*xopEquals)(p1, p2);
+        else
+            // BUG: relies on the GC not moving objects
+            c = (memcmp(p1, p2, m_init.length) == 0);
+        return c;
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        int c = 0;
+
+        // Regard null references as always being "less than"
+        if (p1 != p2)
+        {
+            if (p1)
+            {   if (!p2)
+                    c = 1;
+                else if (xopCmp)
+                    c = (*xopCmp)(p1, p2);
+                else
+                    // BUG: relies on the GC not moving objects
+                    c = memcmp(p1, p2, m_init.length);
+            }
+            else
+                c = -1;
+        }
+        return c;
+    }
+
+    size_t tsize()
+    {
+        return m_init.length;
+    }
+
+    void[] init() { return m_init; }
+
+    uint flags() { return m_flags; }
+
+    char[] name;
+    void[] m_init;      // initializer; never null
+
+    hash_t function(void*)    xtoHash;
+    int function(void*,void*) xopEquals;
+    int function(void*,void*) xopCmp;
+    char[] function(void*)    xtoString;
+
+    uint m_flags;
+}
+
+class TypeInfo_Tuple : TypeInfo
+{
+    TypeInfo[] elements;
+
+    char[] toString()
+    {
+        char[] s;
+        s = "(";
+        foreach (i, element; elements)
+        {
+            if (i)
+                s ~= ',';
+            s ~= element.toString();
+        }
+        s ~= ")";
+        return s;
+    }
+
+    int opEquals(Object o)
+    {
+        if (this is o)
+            return 1;
+
+        auto t = cast(TypeInfo_Tuple)o;
+        if (t && elements.length == t.elements.length)
+        {
+            for (size_t i = 0; i < elements.length; i++)
+            {
+                if (elements[i] != t.elements[i])
+                    return 0;
+            }
+            return 1;
+        }
+        return 0;
+    }
+
+    hash_t getHash(void *p)
+    {
+        assert(0);
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        assert(0);
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        assert(0);
+    }
+
+    size_t tsize()
+    {
+        assert(0);
+    }
+
+    void swap(void *p1, void *p2)
+    {
+        assert(0);
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Exception
+////////////////////////////////////////////////////////////////////////////////
+
+
+class Exception : Object
+{
+    interface TraceInfo
+    {
+        int opApply( int delegate( inout char[] ) );
+    }
+
+    char[]      msg;
+    char[]      file;
+    size_t      line;
+    TraceInfo   info;
+    Exception   next;
+
+    this( char[] msg, Exception next = null )
+    {
+        this.msg = msg;
+        this.next = next;
+        this.info = traceContext();
+    }
+
+    this( char[] msg, char[] file, size_t line, Exception next = null )
+    {
+        this(msg, next);
+        this.file = file;
+        this.line = line;
+        this.info = traceContext();
+    }
+
+    char[] toString()
+    {
+        return msg;
+    }
+}
+
+
+alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
+private TraceHandler traceHandler = null;
+
+
+/**
+ * Overrides the default trace hander with a user-supplied version.
+ *
+ * Params:
+ *  h = The new trace handler.  Set to null to use the default handler.
+ */
+extern (C) void  rt_setTraceHandler( TraceHandler h )
+{
+    traceHandler = h;
+}
+
+
+/**
+ * This function will be called when an Exception is constructed.  The
+ * user-supplied trace handler will be called if one has been supplied,
+ * otherwise no trace will be generated.
+ *
+ * Params:
+ *  ptr = A pointer to the location from which to generate the trace, or null
+ *        if the trace should be generated from within the trace handler
+ *        itself.
+ *
+ * Returns:
+ *  An object describing the current calling context or null if no handler is
+ *  supplied.
+ */
+Exception.TraceInfo traceContext( void* ptr = null )
+{
+    if( traceHandler is null )
+        return null;
+    return traceHandler( ptr );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// ModuleInfo
+////////////////////////////////////////////////////////////////////////////////
+
+
+enum
+{
+    MIctorstart  = 1,   // we've started constructing it
+    MIctordone   = 2,   // finished construction
+    MIstandalone = 4,   // module ctor does not depend on other module
+                        // ctors being done first
+    MIhasictor   = 8,   // has ictor member
+}
+
+
+class ModuleInfo
+{
+    char[]          name;
+    ModuleInfo[]    importedModules;
+    ClassInfo[]     localClasses;
+    uint            flags;
+
+    void function() ctor;       // module static constructor (order dependent)
+    void function() dtor;       // module static destructor
+    void function() unitTest;   // module unit tests
+
+    void* xgetMembers;          // module getMembers() function
+
+    void function() ictor;      // module static constructor (order independent)
+
+    static int opApply( int delegate( inout ModuleInfo ) dg )
+    {
+        int ret = 0;
+
+        foreach( m; _moduleinfo_array )
+        {
+            ret = dg( m );
+            if( ret )
+                break;
+        }
+        return ret;
+    }
+}
+
+
+// this gets initialized in _moduleCtor()
+extern (C) ModuleInfo[] _moduleinfo_array;
+
+// This linked list is created by a compiler generated function inserted
+// into the .ctor list by the compiler.
+struct ModuleReference
+{
+    ModuleReference* next;
+    ModuleInfo       mod;
+}
+extern (C) ModuleReference* _Dmodule_ref;   // start of linked list
+
+// this list is built from the linked list above
+ModuleInfo[] _moduleinfo_dtors;
+uint         _moduleinfo_dtors_i;
+
+/**
+ * Initialize the modules.
+ */
+
+extern (C) void _moduleCtor()
+{
+    debug(PRINTF) printf("_moduleCtor()\n");
+
+    int len = 0;
+    ModuleReference *mr;
+
+    for (mr = _Dmodule_ref; mr; mr = mr.next)
+        len++;
+    _moduleinfo_array = new ModuleInfo[len];
+    len = 0;
+    for (mr = _Dmodule_ref; mr; mr = mr.next)
+    {   _moduleinfo_array[len] = mr.mod;
+        len++;
+    }
+
+    _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
+    debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
+    _moduleIndependentCtors();
+    _moduleCtor2(_moduleinfo_array, 0);
+}
+
+extern (C) void _moduleIndependentCtors()
+{
+    debug(PRINTF) printf("_moduleIndependentCtors()\n");
+    foreach (m; _moduleinfo_array)
+    {
+        if (m && m.flags & MIhasictor && m.ictor)
+        {
+            (*m.ictor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleIndependentCtors() DONE\n");
+}
+
+void _moduleCtor2(ModuleInfo[] mi, int skip)
+{
+    debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
+    for (uint i = 0; i < mi.length; i++)
+    {
+        ModuleInfo m = mi[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
+        if (!m)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr);
+        if (m.flags & MIctordone)
+            continue;
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name.length, m.name.ptr, m);
+
+        if (m.ctor || m.dtor)
+        {
+            if (m.flags & MIctorstart)
+            {   if (skip || m.flags & MIstandalone)
+                    continue;
+                    throw new Exception( "Cyclic dependency in module " ~ m.name );
+            }
+
+            m.flags |= MIctorstart;
+            _moduleCtor2(m.importedModules, 0);
+            if (m.ctor)
+                (*m.ctor)();
+            m.flags &= ~MIctorstart;
+            m.flags |= MIctordone;
+
+            // Now that construction is done, register the destructor
+            //printf("\tadding module dtor x%x\n", m);
+            assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
+            _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
+        }
+        else
+        {
+            m.flags |= MIctordone;
+            _moduleCtor2(m.importedModules, 1);
+        }
+    }
+    debug(PRINTF) printf("_moduleCtor2() DONE\n");
+}
+
+/**
+ * Destruct the modules.
+ */
+
+// Starting the name with "_STD" means under linux a pointer to the
+// function gets put in the .dtors segment.
+
+extern (C) void _moduleDtor()
+{
+    debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
+
+    for (uint i = _moduleinfo_dtors_i; i-- != 0;)
+    {
+        ModuleInfo m = _moduleinfo_dtors[i];
+
+        debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
+        if (m.dtor)
+        {
+            (*m.dtor)();
+        }
+    }
+    debug(PRINTF) printf("_moduleDtor() done\n");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Monitor
+////////////////////////////////////////////////////////////////////////////////
+
+alias Object.Monitor        IMonitor;
+alias void delegate(Object) DEvent;
+
+// NOTE: The dtor callback feature is only supported for monitors that are not
+//       supplied by the user.  The assumption is that any object with a user-
+//       supplied monitor may have special storage or lifetime requirements and
+//       that as a result, storing references to local objects within Monitor
+//       may not be safe or desirable.  Thus, devt is only valid if impl is
+//       null.
+struct Monitor
+{
+    IMonitor impl;
+    /* internal */
+    DEvent[] devt;
+    /* stuff */
+}
+
+Monitor* getMonitor(Object h)
+{
+    return cast(Monitor*) (cast(void**) h)[1];
+}
+
+void setMonitor(Object h, Monitor* m)
+{
+    (cast(void**) h)[1] = m;
+}
+
+extern (C) void _d_monitor_create(Object);
+extern (C) void _d_monitor_destroy(Object);
+extern (C) void _d_monitor_lock(Object);
+extern (C) int  _d_monitor_unlock(Object);
+
+extern (C) void _d_monitordelete(Object h, bool det)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m !is null)
+    {
+        IMonitor i = m.impl;
+        if (i is null)
+        {
+            _d_monitor_devt(m, h);
+            _d_monitor_destroy(h);
+            setMonitor(h, null);
+            return;
+        }
+        if (det && (cast(void*) i) !is (cast(void*) h))
+            delete i;
+        setMonitor(h, null);
+    }
+}
+
+extern (C) void _d_monitorenter(Object h)
+{
+    Monitor* m = getMonitor(h);
+
+    if (m is null)
+    {
+        _d_monitor_create(h);
+        m = getMonitor(h);
+    }
+
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_lock(h);
+        return;
+    }
+    i.lock();
+}
+
+extern (C) void _d_monitorexit(Object h)
+{
+    Monitor* m = getMonitor(h);
+    IMonitor i = m.impl;
+
+    if (i is null)
+    {
+        _d_monitor_unlock(h);
+        return;
+    }
+    i.unlock();
+}
+
+extern (C) void _d_monitor_devt(Monitor* m, Object h)
+{
+    if (m.devt.length)
+    {
+        DEvent[] devt;
+
+        synchronized (h)
+        {
+            devt = m.devt;
+            m.devt = null;
+        }
+        foreach (v; devt)
+        {
+            if (v)
+                v(h);
+        }
+        free(devt.ptr);
+    }
+}
+
+extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (inout v; m.devt)
+        {
+            if (v is null || v == e)
+            {
+                v = e;
+                return;
+            }
+        }
+
+        auto len = m.devt.length + 4; // grow by 4 elements
+        auto pos = m.devt.length;     // insert position
+        auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
+        if (!p)
+            onOutOfMemoryError();
+        m.devt = (cast(DEvent*)p)[0 .. len];
+        m.devt[pos+1 .. len] = null;
+        m.devt[pos] = e;
+    }
+}
+
+extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
+{
+    synchronized (h)
+    {
+        Monitor* m = getMonitor(h);
+        assert(m.impl is null);
+
+        foreach (p, v; m.devt)
+        {
+            if (v == e)
+            {
+                memmove(&m.devt[p],
+                        &m.devt[p+1],
+                        (m.devt.length - p - 1) * DEvent.sizeof);
+                m.devt[$ - 1] = null;
+                return;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/lifetime.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,1052 @@
+/**
+ * This module contains all functions related to an object's lifetime:
+ * allocation, resizing, deallocation, and finalization.
+ *
+ * Copyright: Copyright (C) 2004-2007 Digital Mars, www.digitalmars.com.
+ *            All rights reserved.
+ * License:
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ * Authors:   Walter Bright, Sean Kelly, Tomas Lindquist Olsen
+ */
+module lifetime;
+
+//debug=PRINTF;
+//debug=PRINTF2;
+
+private
+{
+    import tango.stdc.stdlib;
+    import tango.stdc.string;
+    import tango.stdc.stdarg;
+    debug(PRINTF) import tango.stdc.stdio;
+    else debug(PRINTF2) import tango.stdc.stdio;
+}
+
+
+private
+{
+    enum BlkAttr : uint
+    {
+        FINALIZE = 0b0000_0001,
+        NO_SCAN  = 0b0000_0010,
+        NO_MOVE  = 0b0000_0100,
+        ALL_BITS = 0b1111_1111
+    }
+
+    struct BlkInfo
+    {
+        void*  base;
+        size_t size;
+        uint   attr;
+    }
+
+    extern (C) uint gc_getAttr( void* p );
+    extern (C) uint gc_setAttr( void* p, uint a );
+    extern (C) uint gc_clrAttr( void* p, uint a );
+
+    extern (C) void*  gc_malloc( size_t sz, uint ba = 0 );
+    extern (C) void*  gc_calloc( size_t sz, uint ba = 0 );
+    extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
+    extern (C) void   gc_free( void* p );
+
+    extern (C) void*   gc_addrOf( void* p );
+    extern (C) size_t  gc_sizeOf( void* p );
+    extern (C) BlkInfo gc_query( void* p );
+
+    extern (C) bool onCollectResource( Object o );
+    extern (C) void onFinalizeError( ClassInfo c, Exception e );
+    extern (C) void onOutOfMemoryError();
+
+    extern (C) void _d_monitordelete(Object h, bool det = true);
+
+    enum
+    {
+        PAGESIZE = 4096
+    }
+
+    alias bool function(Object) CollectHandler;
+    CollectHandler collectHandler = null;
+}
+
+
+/**
+ *
+ */
+extern (C) Object _d_newclass(ClassInfo ci)
+{
+    void* p;
+
+    debug(PRINTF2) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name.ptr);
+    /+
+    if (ci.flags & 1) // if COM object
+    {   /* COM objects are not garbage collected, they are reference counted
+         * using AddRef() and Release().  They get free'd by C's free()
+         * function called by Release() when Release()'s reference count goes
+         * to zero.
+	 */
+        p = tango.stdc.stdlib.malloc(ci.init.length);
+        if (!p)
+            onOutOfMemoryError();
+    }
+    else
+    +/
+    {
+        p = gc_malloc(ci.init.length,
+                      BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0));
+        debug(PRINTF2) printf(" p = %p\n", p);
+    }
+
+    debug(PRINTF2)
+    {
+        printf("p = %p\n", p);
+        printf("ci = %p, ci.init = %p, len = %d\n", ci, ci.init.ptr, ci.init.length);
+        printf("vptr = %p\n", *cast(void**) ci.init.ptr);
+        printf("vtbl[0] = %p\n", (*cast(void***) ci.init.ptr)[0]);
+        printf("vtbl[1] = %p\n", (*cast(void***) ci.init.ptr)[1]);
+        printf("init[0] = %p\n", (cast(uint**) ci.init.ptr)[0]);
+        printf("init[1] = %p\n", (cast(uint**) ci.init.ptr)[1]);
+        printf("init[2] = %p\n", (cast(uint**) ci.init.ptr)[2]);
+        printf("init[3] = %p\n", (cast(uint**) ci.init.ptr)[3]);
+        printf("init[4] = %p\n", (cast(uint**) ci.init.ptr)[4]);
+    }
+
+    // initialize it
+    // llvmdc does this inline
+    //(cast(byte*) p)[0 .. ci.init.length] = ci.init[];
+
+    debug(PRINTF) printf("initialization done\n");
+    return cast(Object) p;
+}
+
+/**
+ *
+ */
+extern (C) void _d_delinterface(void* p)
+{
+    if (p)
+    {
+        Interface* pi = **cast(Interface ***)p;
+        Object     o  = cast(Object)(p - pi.offset);
+
+        _d_delclass(o);
+        //*p = null;
+    }
+}
+
+// used for deletion
+private extern (D) alias void function(Object) fp_t;
+
+
+/**
+ *
+ */
+extern (C) void _d_delclass(Object p)
+{
+    if (p)
+    {
+        debug(PRINTF) printf("_d_delclass(%p)\n", p);
+
+        ClassInfo **pc = cast(ClassInfo **)p;
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            rt_finalize(cast(void*) p);
+
+            if (c.deallocator)
+            {
+                fp_t fp = cast(fp_t)c.deallocator;
+                (*fp)(p); // call deallocator
+                //*p = null;
+                return;
+            }
+        }
+        else
+        {
+            rt_finalize(cast(void*) p);
+        }
+        gc_free(cast(void*) p);
+        //*p = null;
+    }
+}
+
+/+
+
+/**
+ *
+ */
+struct Array
+{
+    size_t length;
+    void*  data;
+}
+
++/
+
+/**
+ * Allocate a new array of length elements.
+ * ti is the type of the resulting array, or pointer to element.
+ * (For when the array is initialized to 0)
+ */
+extern (C) void* _d_newarrayT(TypeInfo ti, size_t length)
+{
+    void* p;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayT(length = %u, size = %d)\n", length, size);
+    if (length == 0 || size == 0)
+        return null;
+
+    version (D_InlineAsm_X86)
+    {
+        asm
+        {
+            mov     EAX,size        ;
+            mul     EAX,length      ;
+            mov     size,EAX        ;
+            jc      Loverflow       ;
+        }
+    }
+    else
+        size *= length;
+    p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    debug(PRINTF) printf(" p = %p\n", p);
+    memset(p, 0, size);
+    return p;
+
+Loverflow:
+    onOutOfMemoryError();
+    return null;
+}
+
+/**
+ * For when the array has a non-zero initializer.
+ */
+extern (C) void* _d_newarrayiT(TypeInfo ti, size_t length)
+{
+    void* result;
+    auto size = ti.next.tsize();                // array element size
+
+    debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d)\n", length, size);
+
+    if (length == 0 || size == 0)
+        result = null;
+    else
+    {
+        auto initializer = ti.next.init();
+        auto isize = initializer.length;
+        auto q = initializer.ptr;
+        version (D_InlineAsm_X86)
+        {
+            asm
+            {
+                mov     EAX,size        ;
+                mul     EAX,length      ;
+                mov     size,EAX        ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+            size *= length;
+        auto p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        debug(PRINTF) printf(" p = %p\n", p);
+        if (isize == 1)
+            memset(p, *cast(ubyte*)q, size);
+        else if (isize == int.sizeof)
+        {
+            int init = *cast(int*)q;
+            size /= int.sizeof;
+            for (size_t u = 0; u < size; u++)
+            {
+                (cast(int*)p)[u] = init;
+            }
+        }
+        else
+        {
+            for (size_t u = 0; u < size; u += isize)
+            {
+                memcpy(p + u, q, isize);
+            }
+        }
+        result = p;
+    }
+    return result;
+
+Loverflow:
+    onOutOfMemoryError();
+    return null;
+}
+
+/**
+ *
+ */
+extern (C) void* _d_newarraymT(TypeInfo ti, int ndims, size_t* dims)
+{
+    void* result;
+
+    debug(PRINTF) printf("_d_newarraymT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = null;
+    else
+    {
+        static void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            debug(PRINTF) printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims);
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayT(ti, dim);
+                return r[0 .. dim];
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        result = foo(ti, dims, ndims).ptr;
+        debug(PRINTF) printf("result = %p\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, *dims++);
+            }
+        }
+    }
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_newarraymiT(TypeInfo ti, int ndims, size_t* dims)
+{
+    void* result;
+
+    debug(PRINTF) printf("_d_newarraymiT(ndims = %d)\n", ndims);
+    if (ndims == 0)
+        result = null;
+    else
+    {
+        static void[] foo(TypeInfo ti, size_t* pdim, int ndims)
+        {
+            size_t dim = *pdim;
+            void[] p;
+
+            if (ndims == 1)
+            {
+                auto r = _d_newarrayiT(ti, dim);
+                p = r[0 .. dim];
+            }
+            else
+            {
+                p = gc_malloc(dim * (void[]).sizeof + 1)[0 .. dim];
+                for (int i = 0; i < dim; i++)
+                {
+                    (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1);
+                }
+            }
+            return p;
+        }
+
+        result = foo(ti, dims, ndims).ptr;
+        debug(PRINTF) printf("result = %p\n", result);
+
+        version (none)
+        {
+            for (int i = 0; i < ndims; i++)
+            {
+                printf("index %d: %d\n", i, *dims++);
+                printf("init = %d\n", *dims++);
+            }
+        }
+    }
+    return result;
+}
+
+/+
+
+/**
+ *
+ */
+void* _d_allocmemory(size_t nbytes)
+{
+    return gc_malloc(nbytes);
+}
+
++/
+
+/**
+ * for allocating a single POD value
+ */
+extern (C) void* _d_allocmemoryT(TypeInfo ti)
+{
+    return gc_malloc(ti.tsize(), (ti.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+}
+
+/**
+ *
+ */
+extern (C) void _d_delarray(size_t plength, void* pdata)
+{
+//     if (p)
+//     {
+        assert(!plength || pdata);
+
+        if (pdata)
+            gc_free(pdata);
+//         p.data = null;
+//         p.length = 0;
+//     }
+}
+
+/**
+ *
+ */
+extern (C) void _d_delmemory(void* p)
+{
+    if (p)
+    {
+        gc_free(p);
+        //*p = null;
+    }
+}
+
+/** 
+ * 
+ */ 
+extern (C) void _d_callinterfacefinalizer(void *p)
+{
+    if (p)
+    {
+        Interface *pi = **cast(Interface ***)p;
+        Object o = cast(Object)(p - pi.offset);
+        rt_finalize(cast(void*)o);
+    }
+}
+
+/**
+ *
+ */
+extern (C) void _d_callfinalizer(void* p)
+{
+    rt_finalize( p );
+}
+
+
+/**
+ *
+ */
+extern (C) void  rt_setCollectHandler(CollectHandler h)
+{
+    collectHandler = h;
+}
+
+/**
+ *
+ */
+extern (C) void rt_finalize(void* p, bool det = true)
+{
+    debug(PRINTF) printf("rt_finalize(p = %p)\n", p);
+
+    if (p) // not necessary if called from gc
+    {
+        ClassInfo** pc = cast(ClassInfo**)p;
+
+        if (*pc)
+        {
+            ClassInfo c = **pc;
+
+            try
+            {
+                if (det || collectHandler is null || collectHandler(cast(Object)p))
+                {
+                    do
+                    {
+                        if (c.destructor)
+                        {
+                            debug(PRINTF) printf("calling dtor of %.*s\n", c.name.length, c.name.ptr);
+                            fp_t fp = cast(fp_t)c.destructor;
+                            (*fp)(cast(Object)p); // call destructor
+                        }
+                        c = c.base;
+                    } while (c);
+                }
+                if ((cast(void**)p)[1]) // if monitor is not null
+                    _d_monitordelete(cast(Object)p, det);
+            }
+            catch (Exception e)
+            {
+                onFinalizeError(**pc, e);
+            }
+            finally
+            {
+                *pc = null; // zero vptr
+            }
+        }
+    }
+}
+
+/**
+ * Resize dynamic arrays with 0 initializers.
+ */
+extern (C) byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
+in
+{
+    assert(ti);
+    assert(!plength || pdata);
+}
+body
+{
+    byte* newdata;
+    size_t sizeelem = ti.next.tsize();
+
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthT(sizeelem = %d, newlength = %d)\n", sizeelem, newlength);
+        printf("\tp.data = %p, p.length = %d\n", pdata, plength);
+    }
+
+    if (newlength)
+    {
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov EAX, newlength;
+                mul EAX, sizeelem;
+                mov newsize, EAX;
+                jc  Loverflow;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        if (pdata)
+        {
+            newdata = pdata;
+            if (newlength > plength)
+            {
+                size_t size = plength * sizeelem;
+                auto   info = gc_query(pdata);
+
+                if (info.size <= newsize || info.base != pdata)
+                {
+                    if (info.size >= PAGESIZE && info.base == pdata)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = pdata[0 .. size];
+                }
+             L1:
+                newdata[size .. newsize] = 0;
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_calloc(newsize + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+    }
+    else
+    {
+        newdata = pdata;
+    }
+
+    return newdata;
+
+Loverflow:
+    onOutOfMemoryError();
+    return null;
+}
+
+
+/**
+ * Resize arrays for non-zero initializers.
+ *      p               pointer to array lvalue to be updated
+ *      newlength       new .length property of array
+ *      sizeelem        size of each element of array
+ *      initsize        size of initializer
+ *      ...             initializer
+ */
+extern (C) byte* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata)
+in
+{
+    assert(!plength || pdata);
+}
+body
+{
+    byte* newdata;
+    TypeInfo tinext = ti.next;
+    size_t sizeelem = tinext.tsize();
+    void[] initializer = tinext.init();
+    size_t initsize = initializer.length;
+
+    assert(sizeelem);
+    assert(initsize);
+    assert(initsize <= sizeelem);
+    assert((sizeelem / initsize) * initsize == sizeelem);
+
+    debug(PRINTF)
+    {
+        printf("_d_arraysetlengthiT(sizeelem = %d, newlength = %d, initsize = %d)\n", sizeelem, newlength, initsize);
+        printf("\tp.data = %p, p.length = %d\n", pdata, plength);
+    }
+
+    if (newlength)
+    {
+        version (D_InlineAsm_X86)
+        {
+            size_t newsize = void;
+
+            asm
+            {
+                mov     EAX,newlength   ;
+                mul     EAX,sizeelem    ;
+                mov     newsize,EAX     ;
+                jc      Loverflow       ;
+            }
+        }
+        else
+        {
+            size_t newsize = sizeelem * newlength;
+
+            if (newsize / newlength != sizeelem)
+                goto Loverflow;
+        }
+        debug(PRINTF) printf("newsize = %x, newlength = %x\n", newsize, newlength);
+
+        size_t size = plength * sizeelem;
+
+        if (pdata)
+        {
+            newdata = pdata;
+            if (newlength > plength)
+            {
+                auto info = gc_query(pdata);
+
+                if (info.size <= newsize || info.base != pdata)
+                {
+                    if (info.size >= PAGESIZE && info.base == pdata)
+                    {   // Try to extend in-place
+                        auto u = gc_extend(pdata, (newsize + 1) - info.size, (newsize + 1) - info.size);
+                        if (u)
+                        {
+                            goto L1;
+                        }
+                    }
+                    newdata = cast(byte *)gc_malloc(newsize + 1, info.attr);
+                    newdata[0 .. size] = pdata[0 .. size];
+                L1: ;
+                }
+            }
+        }
+        else
+        {
+            newdata = cast(byte *)gc_malloc(newsize + 1, !(tinext.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        }
+
+        auto q = initializer.ptr; // pointer to initializer
+
+        if (newsize > size)
+        {
+            if (initsize == 1)
+            {
+                debug(PRINTF) printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q);
+                newdata[size .. newsize] = *(cast(byte*)q);
+            }
+            else
+            {
+                for (size_t u = size; u < newsize; u += initsize)
+                {
+                    memcpy(newdata + u, q, initsize);
+                }
+            }
+        }
+    }
+    else
+    {
+        newdata = pdata;
+    }
+
+    return newdata;
+
+Loverflow:
+    onOutOfMemoryError();
+    return null;
+}
+
+/+
+
+/**
+ * Append y[] to array x[].
+ * size is size of each array element.
+ */
+extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(px.data);
+    auto length = px.length;
+    auto newlength = length + y.length;
+    auto newsize = newlength * sizeelem;
+
+    if (info.size < newsize || info.base != px.data)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == px.data)
+        {   // Try to extend in-place
+            auto u = gc_extend(px.data, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        newdata = cast(byte *)gc_malloc(newCapacity(newlength, sizeelem) + 1, info.attr);
+        memcpy(newdata, px.data, length * sizeelem);
+        px.data = newdata;
+    }
+  L1:
+    px.length = newlength;
+    memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem);
+    return *cast(long*)px;
+}
+
+
+/**
+ *
+ */
+size_t newCapacity(size_t newlength, size_t size)
+{
+    version(none)
+    {
+        size_t newcap = newlength * size;
+    }
+    else
+    {
+        /*
+         * Better version by Dave Fladebo:
+         * This uses an inverse logorithmic algorithm to pre-allocate a bit more
+         * space for larger arrays.
+         * - Arrays smaller than PAGESIZE bytes are left as-is, so for the most
+         * common cases, memory allocation is 1 to 1. The small overhead added
+         * doesn't affect small array perf. (it's virtually the same as
+         * current).
+         * - Larger arrays have some space pre-allocated.
+         * - As the arrays grow, the relative pre-allocated space shrinks.
+         * - The logorithmic algorithm allocates relatively more space for
+         * mid-size arrays, making it very fast for medium arrays (for
+         * mid-to-large arrays, this turns out to be quite a bit faster than the
+         * equivalent realloc() code in C, on Linux at least. Small arrays are
+         * just as fast as GCC).
+         * - Perhaps most importantly, overall memory usage and stress on the GC
+         * is decreased significantly for demanding environments.
+         */
+        size_t newcap = newlength * size;
+        size_t newext = 0;
+
+        if (newcap > PAGESIZE)
+        {
+            //double mult2 = 1.0 + (size / log10(pow(newcap * 2.0,2.0)));
+
+            // redo above line using only integer math
+
+            static int log2plus1(size_t c)
+            {   int i;
+
+                if (c == 0)
+                    i = -1;
+                else
+                    for (i = 1; c >>= 1; i++)
+                    {
+                    }
+                return i;
+            }
+
+            /* The following setting for mult sets how much bigger
+             * the new size will be over what is actually needed.
+             * 100 means the same size, more means proportionally more.
+             * More means faster but more memory consumption.
+             */
+            //long mult = 100 + (1000L * size) / (6 * log2plus1(newcap));
+            long mult = 100 + (1000L * size) / log2plus1(newcap);
+
+            // testing shows 1.02 for large arrays is about the point of diminishing return
+            if (mult < 102)
+                mult = 102;
+            newext = cast(size_t)((newcap * mult) / 100);
+            newext -= newext % size;
+            debug(PRINTF) printf("mult: %2.2f, alloc: %2.2f\n",mult/100.0,newext / cast(double)size);
+        }
+        newcap = newext > newcap ? newext : newcap;
+        debug(PRINTF) printf("newcap = %d, newlength = %d, size = %d\n", newcap, newlength, size);
+    }
+    return newcap;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arrayappendcT(TypeInfo ti, inout byte[] x, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    auto info = gc_query(x.ptr);
+    auto length = x.length;
+    auto newlength = length + 1;
+    auto newsize = newlength * sizeelem;
+
+    assert(info.size == 0 || length * sizeelem <= info.size);
+
+    debug(PRINTF) printf("_d_arrayappendcT(sizeelem = %d, ptr = %p, length = %d, cap = %d)\n", sizeelem, x.ptr, x.length, info.size);
+
+    if (info.size <= newsize || info.base != x.ptr)
+    {   byte* newdata;
+
+        if (info.size >= PAGESIZE && info.base == x.ptr)
+        {   // Try to extend in-place
+            auto u = gc_extend(x.ptr, (newsize + 1) - info.size, (newsize + 1) - info.size);
+            if (u)
+            {
+                goto L1;
+            }
+        }
+        debug(PRINTF) printf("_d_arrayappendcT(length = %d, newlength = %d, cap = %d)\n", length, newlength, info.size);
+        auto newcap = newCapacity(newlength, sizeelem);
+        assert(newcap >= newlength * sizeelem);
+        newdata = cast(byte *)gc_malloc(newcap + 1, info.attr);
+        memcpy(newdata, x.ptr, length * sizeelem);
+        (cast(void**)(&x))[1] = newdata;
+    }
+  L1:
+    byte *argp = cast(byte *)(&ti + 2);
+
+    *cast(size_t *)&x = newlength;
+    x.ptr[length * sizeelem .. newsize] = argp[0 .. sizeelem];
+    assert((cast(size_t)x.ptr & 15) == 0);
+    assert(gc_sizeOf(x.ptr) > x.length * sizeelem);
+    return x;
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, sizeelem, result.length, result.ptr);
+    assert(result.length == x.length + y.length);
+    for (size_t i = 0; i < x.length * sizeelem; i++)
+        assert((cast(byte*)result)[i] == (cast(byte*)x)[i]);
+    for (size_t i = 0; i < y.length * sizeelem; i++)
+        assert((cast(byte*)result)[x.length * sizeelem + i] == (cast(byte*)y)[i]);
+
+    size_t cap = gc_sizeOf(result.ptr);
+    assert(!cap || cap > result.length * sizeelem);
+}
+body
+{
+    version (none)
+    {
+        /* Cannot use this optimization because:
+         *  char[] a, b;
+         *  char c = 'a';
+         *  b = a ~ c;
+         *  c = 'b';
+         * will change the contents of b.
+         */
+        if (!y.length)
+            return x;
+        if (!x.length)
+            return y;
+    }
+
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr);
+    auto sizeelem = ti.next.tsize();            // array element size
+    debug(PRINTF) printf("_d_arraycatT(%d,%p ~ %d,%p sizeelem = %d)\n", x.length, x.ptr, y.length, y.ptr, sizeelem);
+    size_t xlen = x.length * sizeelem;
+    size_t ylen = y.length * sizeelem;
+    size_t len  = xlen + ylen;
+
+    if (!len)
+        return null;
+
+    byte* p = cast(byte*)gc_malloc(len + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    memcpy(p, x.ptr, xlen);
+    memcpy(p + xlen, y.ptr, ylen);
+    p[len] = 0;
+    return p[0 .. x.length + y.length];
+}
+
+
+/**
+ *
+ */
+extern (C) byte[] _d_arraycatnT(TypeInfo ti, uint n, ...)
+{   void* a;
+    size_t length;
+    byte[]* p;
+    uint i;
+    byte[] b;
+    auto size = ti.next.tsize(); // array element size
+
+    p = cast(byte[]*)(&n + 1);
+
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        length += b.length;
+    }
+    if (!length)
+        return null;
+
+    a = gc_malloc(length * size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+    p = cast(byte[]*)(&n + 1);
+
+    uint j = 0;
+    for (i = 0; i < n; i++)
+    {
+        b = *p++;
+        if (b.length)
+        {
+            memcpy(a + j, b.ptr, b.length * size);
+            j += b.length * size;
+        }
+    }
+
+    byte[] result;
+    *cast(int *)&result = length;       // jam length
+    (cast(void **)&result)[1] = a;      // jam ptr
+    return result;
+}
+
+
+/**
+ *
+ */
+extern (C) void* _d_arrayliteralT(TypeInfo ti, size_t length, ...)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    void* result;
+
+    debug(PRINTF) printf("_d_arrayliteralT(sizeelem = %d, length = %d)\n", sizeelem, length);
+    if (length == 0 || sizeelem == 0)
+        result = null;
+    else
+    {
+        result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+
+        va_list q;
+        va_start!(size_t)(q, length);
+
+        size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);
+
+        if (stacksize == sizeelem)
+        {
+            memcpy(result, q, length * sizeelem);
+        }
+        else
+        {
+            for (size_t i = 0; i < length; i++)
+            {
+                memcpy(result + i * sizeelem, q, sizeelem);
+                q += stacksize;
+            }
+        }
+
+        va_end(q);
+    }
+    return result;
+}
+
++/
+
+
+/**
+ * Support for array.dup property.
+ */
+struct Array2
+{
+    size_t length;
+    void*  ptr;
+}
+
+
+/**
+ *
+ */
+extern (C) Array2 _adDupT(TypeInfo ti, Array2 a)
+out (result)
+{
+    auto sizeelem = ti.next.tsize();            // array element size
+    assert(memcmp(result.ptr, a.ptr, a.length * sizeelem) == 0);
+}
+body
+{
+    Array2 r;
+
+    if (a.length)
+    {
+        auto sizeelem = ti.next.tsize();                // array element size
+        auto size = a.length * sizeelem;
+        r.ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+        r.length = a.length;
+        memcpy(r.ptr, a.ptr, size);
+    }
+    return r;
+}
+
+
+unittest
+{
+    int[] a;
+    int[] b;
+    int i;
+
+    a = new int[3];
+    a[0] = 1; a[1] = 2; a[2] = 3;
+    b = a.dup;
+    assert(b.length == 3);
+    for (i = 0; i < 3; i++)
+        assert(b[i] == i + 1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/llvmdc.mak	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,174 @@
+# Makefile to build the LLVMDC compiler runtime D library for Linux
+# Designed to work with GNU make
+# Targets:
+#	make
+#		Same as make all
+#	make lib
+#		Build the compiler runtime library
+#   make doc
+#       Generate documentation
+#	make clean
+#		Delete unneeded files created by build process
+
+LIB_TARGET=libtango-base-llvmdc.a
+LIB_MASK=libtango-base-llvmdc*.a
+
+LIB_TARGET_C=libtango-base-c-llvmdc.a
+LIB_MASK_C=libtango-base-c-llvmdc*.a
+
+CP=cp -f
+RM=rm -f
+MD=mkdir -p
+
+#CFLAGS=-O3 $(ADD_CFLAGS)
+CFLAGS=-g $(ADD_CFLAGS)
+
+#DFLAGS=-release -O3 -inline -w $(ADD_DFLAGS)
+DFLAGS=-g -w $(ADD_DFLAGS)
+
+#TFLAGS=-O3 -inline -w $(ADD_DFLAGS)
+TFLAGS=-g -w $(ADD_DFLAGS)
+
+DOCFLAGS=-version=DDoc
+
+CC=gcc
+LC=llvm-ar rsv
+CLC=ar rsv
+DC=llvmdc
+LLC=llvm-as
+
+LIB_DEST=..
+
+.SUFFIXES: .s .S .c .cpp .d .ll .html .o .bc
+
+.s.o:
+	$(CC) -c $(CFLAGS) $< -o$@
+
+.S.o:
+	$(CC) -c $(CFLAGS) $< -o$@
+
+.c.o:
+	$(CC) -c $(CFLAGS) $< -o$@
+
+.cpp.o:
+	g++ -c $(CFLAGS) $< -o$@
+
+.d.bc:
+	$(DC) -c $(DFLAGS) $< -of$@
+
+.d.html:
+	$(DC) -c -o- $(DOCFLAGS) -Df$*.html llvmdc.ddoc $<
+
+targets : lib doc
+all     : lib doc
+lib     : llvmdc.lib llvmdc.clib
+doc     : llvmdc.doc
+
+######################################################
+OBJ_C= \
+    monitor.o \
+    critical.o
+
+OBJ_BASE= \
+    aaA.bc \
+    aApply.bc \
+    aApplyR.bc \
+    adi.bc \
+    arrayInit.bc \
+    cast.bc \
+    dmain2.bc \
+    eh.bc \
+    genobj.bc \
+    lifetime.bc \
+    memory.bc \
+    qsort2.bc \
+    switch.bc \
+
+OBJ_UTIL= \
+    util/console.bc \
+    util/ctype.bc \
+    util/string.bc \
+    util/utf.bc
+
+OBJ_LLVMDC= \
+    llvmdc/bitmanip.bc \
+    llvmdc/vararg.bc
+
+OBJ_TI= \
+    typeinfo/ti_AC.bc \
+    typeinfo/ti_Acdouble.bc \
+    typeinfo/ti_Acfloat.bc \
+    typeinfo/ti_Acreal.bc \
+    typeinfo/ti_Adouble.bc \
+    typeinfo/ti_Afloat.bc \
+    typeinfo/ti_Ag.bc \
+    typeinfo/ti_Aint.bc \
+    typeinfo/ti_Along.bc \
+    typeinfo/ti_Areal.bc \
+    typeinfo/ti_Ashort.bc \
+    typeinfo/ti_byte.bc \
+    typeinfo/ti_C.bc \
+    typeinfo/ti_cdouble.bc \
+    typeinfo/ti_cfloat.bc \
+    typeinfo/ti_char.bc \
+    typeinfo/ti_creal.bc \
+    typeinfo/ti_dchar.bc \
+    typeinfo/ti_delegate.bc \
+    typeinfo/ti_double.bc \
+    typeinfo/ti_float.bc \
+    typeinfo/ti_idouble.bc \
+    typeinfo/ti_ifloat.bc \
+    typeinfo/ti_int.bc \
+    typeinfo/ti_ireal.bc \
+    typeinfo/ti_long.bc \
+    typeinfo/ti_ptr.bc \
+    typeinfo/ti_real.bc \
+    typeinfo/ti_short.bc \
+    typeinfo/ti_ubyte.bc \
+    typeinfo/ti_uint.bc \
+    typeinfo/ti_ulong.bc \
+    typeinfo/ti_ushort.bc \
+    typeinfo/ti_void.bc \
+    typeinfo/ti_wchar.bc
+
+ALL_OBJS= \
+    $(OBJ_BASE) \
+    $(OBJ_UTIL) \
+    $(OBJ_TI) \
+    $(OBJ_LLVMDC)
+
+######################################################
+
+ALL_DOCS=
+
+######################################################
+
+llvmdc.lib : $(LIB_TARGET)
+
+$(LIB_TARGET) : $(ALL_OBJS)
+	$(RM) $@
+	$(LC) $@ $(ALL_OBJS)
+
+llvmdc.clib : $(LIB_TARGET_C)
+
+$(LIB_TARGET_C) : $(OBJ_C)
+	$(RM) $@
+	$(CLC) $@ $(OBJ_C)
+
+llvmdc.doc : $(ALL_DOCS)
+	echo No documentation available.
+
+######################################################
+
+clean :
+	find . -name "*.di" | xargs $(RM)
+	$(RM) $(ALL_OBJS)
+	$(RM) $(OBJ_C)
+	$(RM) $(ALL_DOCS)
+	$(RM) $(LIB_MASK)
+	$(RM) $(LIB_MASK_C)
+
+install :
+	$(MD) $(LIB_DEST)
+	$(CP) $(LIB_MASK) $(LIB_DEST)/.
+	$(CP) $(LIB_MASK_C) $(LIB_DEST)/.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/llvmdc/bitmanip.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,81 @@
+/*
+ * D phobos intrinsics for LLVMDC
+ *
+ * From GDC ... public domain!
+ */
+module llvmdc.bitmanip;
+
+// Check for the right compiler
+version(LLVMDC)
+{
+    // OK
+}
+else
+{
+    static assert(false, "This module is only valid for LLVMDC");
+}
+
+int bsf(uint v)
+{
+    uint m = 1;
+    uint i;
+    for (i = 0; i < 32; i++,m<<=1) {
+        if (v&m)
+        return i;
+    }
+    return i; // supposed to be undefined
+}
+
+int bsr(uint v)
+{
+    uint m = 0x80000000;
+    uint i;
+    for (i = 32; i ; i--,m>>>=1) {
+    if (v&m)
+        return i-1;
+    }
+    return i; // supposed to be undefined
+}
+
+int bt(uint *p, uint bitnum)
+{
+    return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ;
+}
+
+int btc(uint *p, uint bitnum)
+{
+    uint * q = p + (bitnum / (uint.sizeof*8));
+    uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
+    int result = *q & mask;
+    *q ^= mask;
+    return result ? -1 : 0;
+}
+
+int btr(uint *p, uint bitnum)
+{
+    uint * q = p + (bitnum / (uint.sizeof*8));
+    uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
+    int result = *q & mask;
+    *q &= ~mask;
+    return result ? -1 : 0;
+}
+
+int bts(uint *p, uint bitnum)
+{
+    uint * q = p + (bitnum / (uint.sizeof*8));
+    uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
+    int result = *q & mask;
+    *q |= mask;
+    return result ? -1 : 0;
+}
+
+pragma(intrinsic, "llvm.bswap.i32")
+    uint bswap(uint val);
+
+ubyte  inp(uint p) { return 0; }
+ushort inpw(uint p) { return 0; }
+uint   inpl(uint p) { return 0; }
+
+ubyte  outp(uint p, ubyte v) { return v; }
+ushort outpw(uint p, ushort v) { return v; }
+uint   outpl(uint p, uint v) { return v; }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/llvmdc/vararg.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,43 @@
+/*
+ * This module holds the implementation of special vararg templates for D style var args.
+ *
+ * Provides the functions tango.core.Vararg expects to be present!
+ */
+
+module llvmdc.Vararg;
+
+// Check for the right compiler
+version(LLVMDC)
+{
+    // OK
+}
+else
+{
+    static assert(false, "This module is only valid for LLVMDC");
+}
+
+alias void* va_list;
+
+void va_start(T) ( out va_list ap, inout T parmn )
+{
+    // not needed !
+}
+
+T va_arg(T)(ref va_list vp)
+{
+    T* arg = cast(T*) vp;
+    // llvmdc always aligns to size_t.sizeof in vararg lists
+    vp = cast(va_list) ( cast(void*) vp + ( ( T.sizeof + size_t.sizeof - 1 ) & ~( size_t.sizeof - 1 ) ) );
+    return *arg;
+}
+
+void va_end( va_list ap )
+{
+    // not needed !
+}
+
+void va_copy( out va_list dst, va_list src )
+{
+    // seems pretty useless !
+    dst = src;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/mars.h	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,105 @@
+
+/*
+ * Placed into the Public Domain
+ * written by Walter Bright, Digital Mars
+ * www.digitalmars.com
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+#include <stddef.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+struct ClassInfo;
+struct Vtbl;
+
+typedef struct Vtbl
+{
+    size_t len;
+    void **vptr;
+} Vtbl;
+
+typedef struct Interface
+{
+    struct ClassInfo *classinfo;
+    struct Vtbl vtbl;
+    int offset;
+} Interface;
+
+typedef struct Object
+{
+    void **vptr;
+    void *monitor;
+} Object;
+
+typedef struct ClassInfo
+{
+    Object object;
+
+    size_t initlen;
+    void *init;
+
+    size_t namelen;
+    char *name;
+
+    Vtbl vtbl;
+
+    size_t interfacelen;
+    Interface *interfaces;
+
+    struct ClassInfo *baseClass;
+
+    void *destructor;
+    void *invariant;
+
+    int flags;
+} ClassInfo;
+
+typedef struct Exception
+{
+    Object object;
+
+    size_t msglen;
+    char*  msg;
+
+    size_t filelen;
+    char*  file;
+
+    size_t line;
+
+    struct Interface *info;
+    struct Exception *next;
+} Exception;
+
+typedef struct Array
+{
+    size_t length;
+    void *ptr;
+} Array;
+
+typedef struct Delegate
+{
+    void *thisptr;
+    void (*funcptr)();
+} Delegate;
+
+void _d_monitorenter(Object *h);
+void _d_monitorexit(Object *h);
+
+int _d_isbaseof(ClassInfo *b, ClassInfo *c);
+Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
+
+Object * _d_newclass(ClassInfo *ci);
+void _d_delclass(Object **p);
+
+void _d_OutOfMemory();
+
+#if __cplusplus
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/memory.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,173 @@
+/**
+ * This module exposes functionality for inspecting and manipulating memory.
+ *
+ * Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
+ *            All rights reserved.
+ * License:
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ * Authors:   Walter Bright, Sean Kelly
+ */
+module memory;
+
+
+private
+{
+    version( linux )
+    {
+        //version = SimpleLibcStackEnd;
+
+        version( SimpleLibcStackEnd )
+        {
+            extern (C) extern void* __libc_stack_end;
+        }
+        else
+        {
+            import tango.stdc.posix.dlfcn;
+        }
+    }
+    version(LLVMDC)
+    {
+        pragma(intrinsic, "llvm.frameaddress")
+        {
+                void* llvm_frameaddress(uint level=0);
+        }
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackBottom()
+{
+    version( Win32 )
+    {
+        asm
+        {
+            naked;
+            mov EAX,FS:4;
+            ret;
+        }
+    }
+    else version( linux )
+    {
+        version( SimpleLibcStackEnd )
+        {
+            return __libc_stack_end;
+        }
+        else
+        {
+            // See discussion: http://autopackage.org/forums/viewtopic.php?t=22
+                static void** libc_stack_end;
+
+                if( libc_stack_end == libc_stack_end.init )
+                {
+                    void* handle = dlopen( null, RTLD_NOW );
+                    libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
+                    dlclose( handle );
+                }
+                return *libc_stack_end;
+        }
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
+
+
+/**
+ *
+ */
+extern (C) void* rt_stackTop()
+{
+    version(LLVMDC)
+    {
+        return llvm_frameaddress();
+    }
+    else version( D_InlineAsm_X86 )
+    {
+        asm
+        {
+            naked;
+            mov EAX, ESP;
+            ret;
+        }
+    }
+    else
+    {
+            static assert( false, "Architecture not supported." );
+    }
+}
+
+
+private
+{
+    version( Win32 )
+    {
+        extern (C)
+        {
+            extern int _data_start__;
+            extern int _bss_end__;
+
+            alias _data_start__ Data_Start;
+            alias _bss_end__    Data_End;
+        }
+    }
+    else version( linux )
+    {
+        extern (C)
+        {
+            extern int _data;
+            extern int __data_start;
+            extern int _end;
+            extern int _data_start__;
+            extern int _data_end__;
+            extern int _bss_start__;
+            extern int _bss_end__;
+            extern int __fini_array_end;
+        }
+
+            alias __data_start  Data_Start;
+            alias _end          Data_End;
+    }
+
+    alias void delegate( void*, void* ) scanFn;
+}
+
+
+/**
+ *
+ */
+extern (C) void rt_scanStaticData( scanFn scan )
+{
+    version( Win32 )
+    {
+        scan( &Data_Start, &Data_End );
+    }
+    else version( linux )
+    {
+        //printf("scanning static data from %p to %p\n", &Data_Start, &Data_End);
+        scan( &Data_Start, &Data_End );
+    }
+    else
+    {
+        static assert( false, "Operating system not supported." );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/monitor.c	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,208 @@
+// D programming language runtime library
+// Public Domain
+// written by Walter Bright, Digital Mars
+// www.digitalmars.com
+
+// This is written in C because nobody has written a pthreads interface
+// to D yet.
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if _WIN32
+#elif linux
+#define USE_PTHREADS	1
+#else
+#endif
+
+#if _WIN32
+#include <windows.h>
+#endif
+
+#if USE_PTHREADS
+#include <pthread.h>
+#endif
+
+#include "mars.h"
+
+// This is what the monitor reference in Object points to
+typedef struct Monitor
+{
+    void* impl; // for user-level monitors
+    Array devt; // for internal monitors
+
+#if _WIN32
+    CRITICAL_SECTION mon;
+#endif
+
+#if USE_PTHREADS
+    pthread_mutex_t mon;
+#endif
+} Monitor;
+
+#define MONPTR(h)	(&((Monitor *)(h)->monitor)->mon)
+
+static volatile int inited;
+
+/* =============================== Win32 ============================ */
+
+#if _WIN32
+
+static CRITICAL_SECTION _monitor_critsec;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {	InitializeCriticalSection(&_monitor_critsec);
+	inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {	inited = 0;
+	DeleteCriticalSection(&_monitor_critsec);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    EnterCriticalSection(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        InitializeCriticalSection(&cs->mon);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    LeaveCriticalSection(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    DeleteCriticalSection(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    EnterCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    LeaveCriticalSection(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
+
+/* =============================== linux ============================ */
+
+#if USE_PTHREADS
+
+// Includes attribute fixes from David Friedman's GDC port
+
+static pthread_mutex_t _monitor_critsec;
+static pthread_mutexattr_t _monitors_attr;
+
+void _STI_monitor_staticctor()
+{
+    if (!inited)
+    {
+	pthread_mutexattr_init(&_monitors_attr);
+	pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
+	pthread_mutex_init(&_monitor_critsec, 0);
+	inited = 1;
+    }
+}
+
+void _STD_monitor_staticdtor()
+{
+    if (inited)
+    {	inited = 0;
+	pthread_mutex_destroy(&_monitor_critsec);
+	pthread_mutexattr_destroy(&_monitors_attr);
+    }
+}
+
+void _d_monitor_create(Object *h)
+{
+    /*
+     * NOTE: Assume this is only called when h->monitor is null prior to the
+     * call.  However, please note that another thread may call this function
+     * at the same time, so we can not assert this here.  Instead, try and
+     * create a lock, and if one already exists then forget about it.
+     */
+
+    //printf("+_d_monitor_create(%p)\n", h);
+    assert(h);
+    Monitor *cs = NULL;
+    pthread_mutex_lock(&_monitor_critsec);
+    if (!h->monitor)
+    {
+        cs = (Monitor *)calloc(sizeof(Monitor), 1);
+        assert(cs);
+        pthread_mutex_init(&cs->mon, & _monitors_attr);
+        h->monitor = (void *)cs;
+        cs = NULL;
+    }
+    pthread_mutex_unlock(&_monitor_critsec);
+    if (cs)
+        free(cs);
+    //printf("-_d_monitor_create(%p)\n", h);
+}
+
+void _d_monitor_destroy(Object *h)
+{
+    //printf("+_d_monitor_destroy(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_destroy(MONPTR(h));
+    free((void *)h->monitor);
+    h->monitor = NULL;
+    //printf("-_d_monitor_destroy(%p)\n", h);
+}
+
+int _d_monitor_lock(Object *h)
+{
+    //printf("+_d_monitor_acquire(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_lock(MONPTR(h));
+    //printf("-_d_monitor_acquire(%p)\n", h);
+}
+
+void _d_monitor_unlock(Object *h)
+{
+    //printf("+_d_monitor_release(%p)\n", h);
+    assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
+    pthread_mutex_unlock(MONPTR(h));
+    //printf("-_d_monitor_release(%p)\n", h);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/qsort2.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,70 @@
+
+/*
+ * Placed into Public Domain
+ * written by Walter Bright
+ * www.digitalmars.com
+ *
+ * This is a public domain version of qsort.d.
+ * All it does is call C's qsort(), but runs a little slower since
+ * it needs to synchronize a global variable.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+//debug=qsort;
+
+private import tango.stdc.stdlib;
+
+struct Array
+{
+    size_t length;
+    void*  ptr;
+}
+
+private TypeInfo tiglobal;
+
+extern (C) int cmp(void* p1, void* p2)
+{
+    return tiglobal.compare(p1, p2);
+}
+
+extern (C) Array _adSort(Array a, TypeInfo ti)
+{
+    synchronized
+    {
+        tiglobal = ti;
+        tango.stdc.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
+    }
+    return a;
+}
+
+
+
+unittest
+{
+    debug(qsort) printf("array.sort.unittest()\n");
+
+    int a[] = new int[10];
+
+    a[0] = 23;
+    a[1] = 1;
+    a[2] = 64;
+    a[3] = 5;
+    a[4] = 6;
+    a[5] = 5;
+    a[6] = 17;
+    a[7] = 3;
+    a[8] = 0;
+    a[9] = -1;
+
+    a.sort;
+
+    for (int i = 0; i < a.length - 1; i++)
+    {
+        //printf("i = %d", i);
+        //printf(" %d %d\n", a[i], a[i + 1]);
+        assert(a[i] <= a[i + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/switch.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,425 @@
+/*
+ *  Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+/*
+ *  Modified by Sean Kelly <sean@f4.ca> for use with Tango.
+ */
+
+private import tango.stdc.string;
+//private import tango.stdc.stdio;
+
+/******************************************************
+ * Support for switch statements switching on strings.
+ * Input:
+ *      table[]         sorted array of strings generated by compiler
+ *      ca              string to look up in table
+ * Output:
+ *      result          index of match in table[]
+ *                      -1 if not in table
+ */
+
+extern (C):
+
+int _d_switch_string(char[][] table, char[] ca)
+in
+{
+    //printf("in _d_switch_string()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        size_t len1 = table[j - 1].length;
+        size_t len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int ci;
+
+            ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
+            assert(ci < 0); // ci==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int cj;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                assert(cj != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                cj = memcmp(table[i].ptr, ca.ptr, ca.length);
+                if (cj == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_string(%.*s)\n", ca.length, ca.ptr);
+    size_t low;
+    size_t high;
+    size_t mid;
+    ptrdiff_t c;
+    char[] pca;
+
+    low = 0;
+    high = table.length;
+
+    version (none)
+    {
+        // Print table
+        printf("ca[] = '%s'\n", cast(char *)ca);
+        for (mid = 0; mid < high; mid++)
+        {
+            pca = table[mid];
+            printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+        }
+    }
+    if (high &&
+        ca.length >= table[0].length &&
+        ca.length <= table[high - 1].length)
+    {
+        // Looking for 0 length string, which would only be at the beginning
+        if (ca.length == 0)
+            return 0;
+
+        char c1 = ca[0];
+
+        // Do binary search
+        while (low < high)
+        {
+            mid = (low + high) >> 1;
+            pca = table[mid];
+            c = cast(ptrdiff_t)(ca.length - pca.length);
+            if (c == 0)
+            {
+                c = cast(ubyte)c1 - cast(ubyte)pca[0];
+                if (c == 0)
+                {
+                    c = memcmp(ca.ptr, pca.ptr, ca.length);
+                    if (c == 0)
+                    {   //printf("found %d\n", mid);
+                        return cast(int)mid;
+                    }
+                }
+            }
+            if (c < 0)
+            {
+                high = mid;
+            }
+            else
+            {
+                low = mid + 1;
+            }
+        }
+    }
+
+    //printf("not found\n");
+    return -1; // not found
+}
+
+unittest
+{
+    switch (cast(char []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_ustring(wchar[][] table, wchar[] ca)
+in
+{
+    //printf("in _d_switch_ustring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        size_t len1 = table[j - 1].length;
+        size_t len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    size_t low;
+    size_t high;
+    size_t mid;
+    ptrdiff_t c;
+    wchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = cast(ptrdiff_t)(ca.length - pca.length);
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return cast(int)mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1;              // not found
+}
+
+
+unittest
+{
+    switch (cast(wchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
+
+
+/**********************************
+ * Same thing, but for wide chars.
+ */
+
+int _d_switch_dstring(dchar[][] table, dchar[] ca)
+in
+{
+    //printf("in _d_switch_dstring()\n");
+    assert(table.length >= 0);
+    assert(ca.length >= 0);
+
+    // Make sure table[] is sorted correctly
+    int j;
+
+    for (j = 1; j < table.length; j++)
+    {
+        size_t len1 = table[j - 1].length;
+        size_t len2 = table[j].length;
+
+        assert(len1 <= len2);
+        if (len1 == len2)
+        {
+            int c;
+
+            c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
+            assert(c < 0);  // c==0 means a duplicate
+        }
+    }
+}
+out (result)
+{
+    int i;
+    int c;
+
+    //printf("out _d_switch_string()\n");
+    if (result == -1)
+    {
+        // Not found
+        for (i = 0; i < table.length; i++)
+        {
+            if (table[i].length == ca.length)
+            {   c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                assert(c != 0);
+            }
+        }
+    }
+    else
+    {
+        assert(0 <= result && result < table.length);
+        for (i = 0; 1; i++)
+        {
+            assert(i < table.length);
+            if (table[i].length == ca.length)
+            {
+                c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
+                if (c == 0)
+                {
+                    assert(i == result);
+                    break;
+                }
+            }
+        }
+    }
+}
+body
+{
+    //printf("body _d_switch_ustring()\n");
+    size_t low;
+    size_t high;
+    size_t mid;
+    ptrdiff_t c;
+    dchar[] pca;
+
+    low = 0;
+    high = table.length;
+
+/*
+    // Print table
+    wprintf("ca[] = '%.*s'\n", ca);
+    for (mid = 0; mid < high; mid++)
+    {
+        pca = table[mid];
+        wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
+    }
+*/
+
+    // Do binary search
+    while (low < high)
+    {
+        mid = (low + high) >> 1;
+        pca = table[mid];
+        c = cast(ptrdiff_t)(ca.length - pca.length);
+        if (c == 0)
+        {
+            c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
+            if (c == 0)
+            {   //printf("found %d\n", mid);
+                return cast(int)mid;
+            }
+        }
+        if (c < 0)
+        {
+            high = mid;
+        }
+        else
+        {
+            low = mid + 1;
+        }
+    }
+    //printf("not found\n");
+    return -1; // not found
+}
+
+
+unittest
+{
+    switch (cast(dchar []) "c")
+    {
+         case "coo":
+         default:
+             break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/typeinfo/ti_AC.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,95 @@
+module typeinfo.ti_AC;
+
+// Object[]
+
+class TypeInfo_AC : TypeInfo_Array
+{
+    hash_t getHash(void *p)
+    {   Object[] s = *cast(Object[]*)p;
+        hash_t hash = 0;
+
+        foreach (Object o; s)
+        {
+            if (o)
+                hash += o.toHash();
+        }
+        return hash;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+
+        if (s1.length == s2.length)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                // Do not pass null's to Object.opEquals()
+                if (o1 is o2 ||
+                    (!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
+                    continue;
+                return 0;
+            }
+            return 1;
+        }
+        return 0;
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        Object[] s1 = *cast(Object[]*)p1;
+        Object[] s2 = *cast(Object[]*)p2;
+        ptrdiff_t c;
+
+        c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
+        if (c == 0)
+        {
+            for (size_t u = 0; u < s1.length; u++)
+            {   Object o1 = s1[u];
+                Object o2 = s2[u];
+
+                if (o1 is o2)
+                    continue;
+
+                // Regard null references as always being "less than"
+                if (o1)
+                {
+                    if (!o2)
+                    {   c = 1;
+                        break;
+                    }
+                    c = o1.opCmp(o2);
+                    if (c)
+                        break;
+                }
+                else
+                {   c = -1;
+                    break;
+                }
+            }
+        }
+        if (c < 0)
+            c = -1;
+        else
+            c = 1;
+        return cast(int)c;
+    }
+
+    size_t tsize()
+    {
+        return (Object[]).sizeof;
+    }
+
+    uint flags()
+    {
+        return 1;
+    }
+
+    TypeInfo next()
+    {
+        return typeid(Object);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtime/internal/typeinfo/ti_Acdouble.d	Fri Aug 01 00:32:06 2008 +0200
@@ -0,0 +1,106 @@
+/*
+ *  Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
+ *  Written by Walter Bright
+ *
+ *  This software is provided 'as-is', without any express or implied
+ *  warranty. In no event will the authors be held liable for any damages
+ *  arising from the use of this software.
+ *
+ *  Permission is granted to anyone to use this software for any purpose,
+ *  including commercial applications, and to alter it and redistribute it
+ *  freely, in both source and binary form, subject to the following
+ *  restrictions:
+ *
+ *  o  The origin of this software must not be misrepresented; you must not
+ *     claim that you wrote the original software. If you use this software
+ *     in a product, an acknowledgment in the product documentation would be
+ *     appreciated but is not required.
+ *  o  Altered source versions must be plainly marked as such, and must not
+ *     be misrepresented as being the original software.
+ *  o  This notice may not be removed or altered from any source
+ *     distribution.
+ */
+
+module typeinfo.ti_Acdouble;
+
+private import typeinfo.ti_cdouble;
+
+// cdouble[]
+
+class TypeInfo_Ar : TypeInfo_Array
+{
+    char[] toString() { return "cdouble[]"; }
+
+    hash_t getHash(void *p)
+    {   cdouble[] s = *cast(cdouble[]*)p;
+        size_t len = s.length;
+        cdouble *str = s.ptr;
+        hash_t hash = 0;
+
+        while (len)
+        {
+            hash *= 9;
+            hash += (cast(uint *)str)[0];
+            hash += (cast(uint *)str)[1];
+            hash += (cast(uint *)str)[2];
+            hash += (cast(uint *)str)[3];
+            str++;
+            len--;
+        }
+
+        return hash;
+    }
+
+    int equals(void *p1, void *p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (len != s2.length)
+            return 0;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_r._equals(s1[u], s2[u]);
+            if (c == 0)
+                return 0;
+        }
+        return 1;
+    }
+
+    int compare(void *p1, void *p2)
+    {
+        cdouble[] s1 = *cast(cdouble[]*)p1;
+        cdouble[] s2 = *cast(cdouble[]*)p2;
+        size_t len = s1.length;
+
+        if (s2.length < len)
+            len = s2.length;
+        for (size_t u = 0; u < len; u++)
+        {
+            int c = TypeInfo_r._compare(s1[u], s2[u]);
+            if (c)
+                return c;
+        }
+        if (s1.length < s2.length)
+            return -1;
+        else if (s1.length > s2.length)
+            return 1;
+        return 0;
+    }
+
+    size_t tsize()
+    {
+        return (cdouble[]).sizeof;
+    }
+
+    uint flags()
+    {
+        return 1;
+    }
+
+    TypeInfo next()
+    {
+        return typeid(cdouble);
+    }
+}