From 41a66cf43733493609cd319750f48b4a19c09593 Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Fri, 8 Oct 2010 15:10:56 +0400 Subject: [PATCH] Use druntime functions for array operations --- druntime.patch | 3573 +++++++++++++++++++++-------------------------- gen/arrays.cpp | 122 +- gen/runtime.cpp | 65 +- 3 files changed, 1773 insertions(+), 1987 deletions(-) diff --git a/druntime.patch b/druntime.patch index 7814ff6b..51b50e58 100644 --- a/druntime.patch +++ b/druntime.patch @@ -1,525 +1,525 @@ -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/ldc/cstdarg.di ldc/druntime/import/ldc/cstdarg.di ---- v2.049/src/druntime/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/import/ldc/cstdarg.di 2010-09-30 22:10:37.000000000 +0400 -@@ -0,0 +1,29 @@ -+/* -+ * vararg support for extern(C) functions -+ */ -+ -+module ldc.cstdarg; -+ -+// Check for the right compiler -+version(LDC) -+{ -+ // OK -+} -+else -+{ -+ static assert(false, "This module is only valid for LDC"); -+} -+ -+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_end) -+ void va_end(va_list args); -+ -+pragma(va_copy) -+ void va_copy(va_list dst, va_list src); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/ldc/intrinsics.di ldc/druntime/import/ldc/intrinsics.di ---- v2.049/src/druntime/import/ldc/intrinsics.di 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/import/ldc/intrinsics.di 2010-10-02 14:01:02.975890001 +0400 -@@ -0,0 +1,413 @@ -+/* -+ * This module holds declarations to LLVM intrinsics. -+ * -+ * See the LLVM language reference for more information: -+ * -+ * - http://llvm.org/docs/LangRef.html#intrinsics -+ * -+ */ -+ -+module ldc.intrinsics; -+ -+// Check for the right compiler -+version(LDC) -+{ -+ // OK -+} -+else -+{ -+ static assert(false, "This module is only valid for LDC"); -+} -+ -+// -+// 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.i#") -+ void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment); -+ -+deprecated { -+ alias llvm_memcpy!(uint) llvm_memcpy_i32; -+ alias llvm_memcpy!(ulong) llvm_memcpy_i64; -+} -+ -+ -+// 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.i#") -+ void llvm_memmove(T)(void* dst, void* src, T len, uint alignment); -+ -+deprecated { -+ alias llvm_memmove!(uint) llvm_memmove_i32; -+ alias llvm_memmove!(ulong) llvm_memmove_i64; -+} -+ -+ -+// 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.i#") -+ void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment); -+ -+deprecated { -+ alias llvm_memset!(uint) llvm_memset_i32; -+ alias llvm_memset!(ulong) llvm_memset_i64; -+} -+ -+ -+// 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.f#") -+ T llvm_sqrt(T)(T val); -+ -+deprecated { -+ alias llvm_sqrt!(float) llvm_sqrt_f32; -+ alias llvm_sqrt!(double) llvm_sqrt_f64; -+ alias llvm_sqrt!(real) llvm_sqrt_f80; // may not actually be .f80 -+} -+ -+ -+// The 'llvm.sin.*' intrinsics return the sine of the operand. -+ -+pragma(intrinsic, "llvm.sin.f#") -+ T llvm_sin(T)(T val); -+ -+deprecated { -+ alias llvm_sin!(float) llvm_sin_f32; -+ alias llvm_sin!(double) llvm_sin_f64; -+ alias llvm_sin!(real) llvm_sin_f80; // may not actually be .f80 -+} -+ -+ -+// The 'llvm.cos.*' intrinsics return the cosine of the operand. -+ -+pragma(intrinsic, "llvm.cos.f#") -+ T llvm_cos(T)(T val); -+ -+deprecated { -+ alias llvm_cos!(float) llvm_cos_f32; -+ alias llvm_cos!(double) llvm_cos_f64; -+ alias llvm_cos!(real) llvm_cos_f80; // may not actually be .f80 -+} -+ -+ -+// 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.f#") -+ T llvm_powi(T)(T val, int power); -+ -+deprecated { -+ alias llvm_powi!(float) llvm_powi_f32; -+ alias llvm_powi!(double) llvm_powi_f64; -+ alias llvm_powi!(real) llvm_powi_f80; // may not actually be .f80 -+} -+ -+ -+// The 'llvm.pow.*' intrinsics return the first operand raised to the specified -+// (positive or negative) power. -+ -+pragma(intrinsic, "llvm.pow.f#") -+ T llvm_pow(T)(T val, T power); -+ -+deprecated { -+ alias llvm_pow!(float) llvm_pow_f32; -+ alias llvm_pow!(double) llvm_pow_f64; -+ alias llvm_pow!(real) llvm_pow_f80; // may not actually be .f80 -+} -+ -+ -+// -+// 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.i#.i#") -+ T llvm_bswap(T)(T val); -+ -+deprecated { -+ alias llvm_bswap!(ushort) llvm_bswap_i16; -+ alias llvm_bswap!(uint) llvm_bswap_i32; -+ alias llvm_bswap!(ulong) llvm_bswap_i64; -+} -+ -+ -+// The 'llvm.ctpop' family of intrinsics counts the number of bits set in a -+// value. -+ -+pragma(intrinsic, "llvm.ctpop.i#") -+ T llvm_ctpop(T)(T src); -+ -+deprecated { -+ alias llvm_ctpop!(ubyte) llvm_ctpop_i8; -+ alias llvm_ctpop!(ushort) llvm_ctpop_i16; -+ alias llvm_ctpop!(uint) llvm_ctpop_i32; -+ alias llvm_ctpop!(ulong) llvm_ctpop_i64; -+} -+ -+ -+// The 'llvm.ctlz' family of intrinsic functions counts the number of leading -+// zeros in a variable. -+ -+pragma(intrinsic, "llvm.ctlz.i#") -+ T llvm_ctlz(T)(T src); -+ -+deprecated { -+ alias llvm_ctlz!(ubyte) llvm_ctlz_i8; -+ alias llvm_ctlz!(ushort) llvm_ctlz_i16; -+ alias llvm_ctlz!(uint) llvm_ctlz_i32; -+ alias llvm_ctlz!(ulong) llvm_ctlz_i64; -+} -+ -+ -+// The 'llvm.cttz' family of intrinsic functions counts the number of trailing -+// zeros. -+ -+pragma(intrinsic, "llvm.cttz.i#") -+ T llvm_cttz(T)(T src); -+ -+deprecated { -+ alias llvm_cttz!(ubyte) llvm_cttz_i8; -+ alias llvm_cttz!(ushort) llvm_cttz_i16; -+ alias llvm_cttz!(uint) llvm_cttz_i32; -+ alias llvm_cttz!(ulong) llvm_cttz_i64; -+} -+ -+ -+// 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.i#") -+ T llvm_part_select(T)(T val, uint loBit, uint hiBit); -+ -+deprecated { -+ alias llvm_part_select!(ubyte) llvm_part_select_i; -+ alias llvm_part_select!(ushort) llvm_part_select_i; -+ alias llvm_part_select!(uint) llvm_part_select_i; -+ alias llvm_part_select!(ulong) llvm_part_select_i; -+} -+ -+ -+// The 'llvm.part.set' family of intrinsic functions replaces a range of bits -+// in an integer value with another integer value. It returns the integer with -+// the replaced bits. -+ -+// TODO -+// declare i17 @llvm.part.set.i17.i9 (i17 %val, i9 %repl, i32 %lo, i32 %hi) -+// declare i29 @llvm.part.set.i29.i9 (i29 %val, i9 %repl, i32 %lo, i32 %hi) -+ -+ -+ -+ -+// -+// ATOMIC OPERATIONS AND SYNCHRONIZATION INTRINSICS -+// -+ -+// The llvm.memory.barrier intrinsic guarantees ordering between specific -+// pairs of memory access types. -+ -+pragma(intrinsic, "llvm.memory.barrier") -+ void llvm_memory_barrier(bool ll, bool ls, bool sl, bool ss, bool device); -+ -+// This loads a value in memory and compares it to a given value. If they are -+// equal, it stores a new value into the memory. -+ -+pragma(intrinsic, "llvm.atomic.cmp.swap.i#.p0i#") -+ T llvm_atomic_cmp_swap(T)(shared T* ptr, T cmp, T val); -+ -+// This intrinsic loads the value stored in memory at ptr and yields the value -+// from memory. It then stores the value in val in the memory at ptr. -+ -+pragma(intrinsic, "llvm.atomic.swap.i#.p0i#") -+ T llvm_atomic_swap(T)(T* ptr, T val); -+ -+// This intrinsic adds delta to the value stored in memory at ptr. It yields -+// the original value at ptr. -+ -+pragma(intrinsic, "llvm.atomic.load.add.i#.p0i#") -+ T llvm_atomic_load_add(T)(shared const T* ptr, T val); -+ -+// This intrinsic subtracts delta to the value stored in memory at ptr. It -+// yields the original value at ptr. -+ -+pragma(intrinsic, "llvm.atomic.load.sub.i#.p0i#") -+ T llvm_atomic_load_sub(T)(T* ptr, T val); -+ -+// These intrinsics bitwise the operation (and, nand, or, xor) delta to the -+// value stored in memory at ptr. It yields the original value at ptr. -+ -+pragma(intrinsic, "llvm.atomic.load.and.i#.p0i#") -+ T llvm_atomic_load_and(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.nand.i#.p0i#") -+ T llvm_atomic_load_nand(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.or.i#.p0i#") -+ T llvm_atomic_load_or(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.xor.i#.p0i#") -+ T llvm_atomic_load_xor(T)(T* ptr, T val); -+ -+// These intrinsics takes the signed or unsigned minimum or maximum of delta -+// and the value stored in memory at ptr. It yields the original value at ptr. -+ -+pragma(intrinsic, "llvm.atomic.load.max.i#.p0i#") -+ T llvm_atomic_load_max(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.min.i#.p0i#") -+ T llvm_atomic_load_min(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.umax.i#.p0i#") -+ T llvm_atomic_load_umax(T)(T* ptr, T val); -+ -+pragma(intrinsic, "llvm.atomic.load.umin.i#.p0i#") -+ T llvm_atomic_load_umin(T)(T* ptr, T val); -+ -+ -+// -+// ARITHMETIC-WITH-OVERFLOW INTRINSICS -+// -+ -+struct OverflowRet(T) { -+ static assert(is(T : int), T.stringof ~ " is not an integer type!"); -+ T result; -+ bool overflow; -+} -+ -+// Signed and unsigned addition -+pragma(intrinsic, "llvm.sadd.with.overflow.i#") -+ OverflowRet!(T) llvm_sadd_with_overflow(T)(T lhs, T rhs); -+ -+pragma(intrinsic, "llvm.uadd.with.overflow.i#") -+ OverflowRet!(T) llvm_uadd_with_overflow(T)(T lhs, T rhs); -+ -+ -+// Signed and unsigned subtraction -+pragma(intrinsic, "llvm.ssub.with.overflow.i#") -+ OverflowRet!(T) llvm_ssub_with_overflow(T)(T lhs, T rhs); -+ -+pragma(intrinsic, "llvm.usub.with.overflow.i#") -+ OverflowRet!(T) llvm_usub_with_overflow(T)(T lhs, T rhs); -+ -+ -+// Signed and unsigned multiplication -+pragma(intrinsic, "llvm.smul.with.overflow.i#") -+ OverflowRet!(T) llvm_smul_with_overflow(T)(T lhs, T rhs); -+ -+/* Note: LLVM documentations says: -+ * Warning: 'llvm.umul.with.overflow' is badly broken. -+ * It is actively being fixed, but it should not currently be used! -+ * -+ * See: http://llvm.org/docs/LangRef.html#int_umul_overflow -+ */ -+//pragma(intrinsic, "llvm.umul.with.overflow.i#") -+// OverflowRet!(T) llvm_umul_with_overflow(T)(T lhs, T rhs); -+ -+ -+// -+// 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(); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/ldc/llvmasm.di ldc/druntime/import/ldc/llvmasm.di ---- v2.049/src/druntime/import/ldc/llvmasm.di 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/import/ldc/llvmasm.di 2010-09-30 22:10:37.000000000 +0400 -@@ -0,0 +1,17 @@ -+module ldc.llvmasm; -+ -+struct __asmtuple_t(T...) -+{ -+ T v; -+} -+ -+pragma(llvm_inline_asm) -+{ -+ void __asm( )(char[] asmcode, char[] constraints, ...); -+ T __asm(T)(char[] asmcode, char[] constraints, ...); -+ -+ template __asmtuple(T...) -+ { -+ __asmtuple_t!(T) __asmtuple(char[] asmcode, char[] constraints, ...); -+ } -+} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/ldc/vararg.d ldc/druntime/import/ldc/vararg.d ---- v2.049/src/druntime/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/import/ldc/vararg.d 2010-09-30 22:10:37.000000000 +0400 -@@ -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 ldc.Vararg; -+ -+// Check for the right compiler -+version(LDC) -+{ -+ // OK -+} -+else -+{ -+ static assert(false, "This module is only valid for LDC"); -+} -+ -+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; -+ // ldc 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; -+} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/object.di ldc/druntime/import/object.di ---- v2.049/src/druntime/import/object.di 2010-09-03 12:28:52.000000000 +0400 -+++ ldc/druntime/import/object.di 2010-10-05 12:47:24.873150000 +0400 -@@ -130,7 +130,7 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/ldc/cstdarg.di druntime/import/ldc/cstdarg.di +--- druntime-old/import/ldc/cstdarg.di 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/import/ldc/cstdarg.di 2010-09-30 22:10:37.000000000 +0400 +@@ -0,0 +1,29 @@ ++/* ++ * vararg support for extern(C) functions ++ */ ++ ++module ldc.cstdarg; ++ ++// Check for the right compiler ++version(LDC) ++{ ++ // OK ++} ++else ++{ ++ static assert(false, "This module is only valid for LDC"); ++} ++ ++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_end) ++ void va_end(va_list args); ++ ++pragma(va_copy) ++ void va_copy(va_list dst, va_list src); +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/ldc/intrinsics.di druntime/import/ldc/intrinsics.di +--- druntime-old/import/ldc/intrinsics.di 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/import/ldc/intrinsics.di 2010-10-02 14:01:02.975890001 +0400 +@@ -0,0 +1,413 @@ ++/* ++ * This module holds declarations to LLVM intrinsics. ++ * ++ * See the LLVM language reference for more information: ++ * ++ * - http://llvm.org/docs/LangRef.html#intrinsics ++ * ++ */ ++ ++module ldc.intrinsics; ++ ++// Check for the right compiler ++version(LDC) ++{ ++ // OK ++} ++else ++{ ++ static assert(false, "This module is only valid for LDC"); ++} ++ ++// ++// 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.i#") ++ void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment); ++ ++deprecated { ++ alias llvm_memcpy!(uint) llvm_memcpy_i32; ++ alias llvm_memcpy!(ulong) llvm_memcpy_i64; ++} ++ ++ ++// 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.i#") ++ void llvm_memmove(T)(void* dst, void* src, T len, uint alignment); ++ ++deprecated { ++ alias llvm_memmove!(uint) llvm_memmove_i32; ++ alias llvm_memmove!(ulong) llvm_memmove_i64; ++} ++ ++ ++// 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.i#") ++ void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment); ++ ++deprecated { ++ alias llvm_memset!(uint) llvm_memset_i32; ++ alias llvm_memset!(ulong) llvm_memset_i64; ++} ++ ++ ++// 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.f#") ++ T llvm_sqrt(T)(T val); ++ ++deprecated { ++ alias llvm_sqrt!(float) llvm_sqrt_f32; ++ alias llvm_sqrt!(double) llvm_sqrt_f64; ++ alias llvm_sqrt!(real) llvm_sqrt_f80; // may not actually be .f80 ++} ++ ++ ++// The 'llvm.sin.*' intrinsics return the sine of the operand. ++ ++pragma(intrinsic, "llvm.sin.f#") ++ T llvm_sin(T)(T val); ++ ++deprecated { ++ alias llvm_sin!(float) llvm_sin_f32; ++ alias llvm_sin!(double) llvm_sin_f64; ++ alias llvm_sin!(real) llvm_sin_f80; // may not actually be .f80 ++} ++ ++ ++// The 'llvm.cos.*' intrinsics return the cosine of the operand. ++ ++pragma(intrinsic, "llvm.cos.f#") ++ T llvm_cos(T)(T val); ++ ++deprecated { ++ alias llvm_cos!(float) llvm_cos_f32; ++ alias llvm_cos!(double) llvm_cos_f64; ++ alias llvm_cos!(real) llvm_cos_f80; // may not actually be .f80 ++} ++ ++ ++// 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.f#") ++ T llvm_powi(T)(T val, int power); ++ ++deprecated { ++ alias llvm_powi!(float) llvm_powi_f32; ++ alias llvm_powi!(double) llvm_powi_f64; ++ alias llvm_powi!(real) llvm_powi_f80; // may not actually be .f80 ++} ++ ++ ++// The 'llvm.pow.*' intrinsics return the first operand raised to the specified ++// (positive or negative) power. ++ ++pragma(intrinsic, "llvm.pow.f#") ++ T llvm_pow(T)(T val, T power); ++ ++deprecated { ++ alias llvm_pow!(float) llvm_pow_f32; ++ alias llvm_pow!(double) llvm_pow_f64; ++ alias llvm_pow!(real) llvm_pow_f80; // may not actually be .f80 ++} ++ ++ ++// ++// 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.i#.i#") ++ T llvm_bswap(T)(T val); ++ ++deprecated { ++ alias llvm_bswap!(ushort) llvm_bswap_i16; ++ alias llvm_bswap!(uint) llvm_bswap_i32; ++ alias llvm_bswap!(ulong) llvm_bswap_i64; ++} ++ ++ ++// The 'llvm.ctpop' family of intrinsics counts the number of bits set in a ++// value. ++ ++pragma(intrinsic, "llvm.ctpop.i#") ++ T llvm_ctpop(T)(T src); ++ ++deprecated { ++ alias llvm_ctpop!(ubyte) llvm_ctpop_i8; ++ alias llvm_ctpop!(ushort) llvm_ctpop_i16; ++ alias llvm_ctpop!(uint) llvm_ctpop_i32; ++ alias llvm_ctpop!(ulong) llvm_ctpop_i64; ++} ++ ++ ++// The 'llvm.ctlz' family of intrinsic functions counts the number of leading ++// zeros in a variable. ++ ++pragma(intrinsic, "llvm.ctlz.i#") ++ T llvm_ctlz(T)(T src); ++ ++deprecated { ++ alias llvm_ctlz!(ubyte) llvm_ctlz_i8; ++ alias llvm_ctlz!(ushort) llvm_ctlz_i16; ++ alias llvm_ctlz!(uint) llvm_ctlz_i32; ++ alias llvm_ctlz!(ulong) llvm_ctlz_i64; ++} ++ ++ ++// The 'llvm.cttz' family of intrinsic functions counts the number of trailing ++// zeros. ++ ++pragma(intrinsic, "llvm.cttz.i#") ++ T llvm_cttz(T)(T src); ++ ++deprecated { ++ alias llvm_cttz!(ubyte) llvm_cttz_i8; ++ alias llvm_cttz!(ushort) llvm_cttz_i16; ++ alias llvm_cttz!(uint) llvm_cttz_i32; ++ alias llvm_cttz!(ulong) llvm_cttz_i64; ++} ++ ++ ++// 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.i#") ++ T llvm_part_select(T)(T val, uint loBit, uint hiBit); ++ ++deprecated { ++ alias llvm_part_select!(ubyte) llvm_part_select_i; ++ alias llvm_part_select!(ushort) llvm_part_select_i; ++ alias llvm_part_select!(uint) llvm_part_select_i; ++ alias llvm_part_select!(ulong) llvm_part_select_i; ++} ++ ++ ++// The 'llvm.part.set' family of intrinsic functions replaces a range of bits ++// in an integer value with another integer value. It returns the integer with ++// the replaced bits. ++ ++// TODO ++// declare i17 @llvm.part.set.i17.i9 (i17 %val, i9 %repl, i32 %lo, i32 %hi) ++// declare i29 @llvm.part.set.i29.i9 (i29 %val, i9 %repl, i32 %lo, i32 %hi) ++ ++ ++ ++ ++// ++// ATOMIC OPERATIONS AND SYNCHRONIZATION INTRINSICS ++// ++ ++// The llvm.memory.barrier intrinsic guarantees ordering between specific ++// pairs of memory access types. ++ ++pragma(intrinsic, "llvm.memory.barrier") ++ void llvm_memory_barrier(bool ll, bool ls, bool sl, bool ss, bool device); ++ ++// This loads a value in memory and compares it to a given value. If they are ++// equal, it stores a new value into the memory. ++ ++pragma(intrinsic, "llvm.atomic.cmp.swap.i#.p0i#") ++ T llvm_atomic_cmp_swap(T)(shared T* ptr, T cmp, T val); ++ ++// This intrinsic loads the value stored in memory at ptr and yields the value ++// from memory. It then stores the value in val in the memory at ptr. ++ ++pragma(intrinsic, "llvm.atomic.swap.i#.p0i#") ++ T llvm_atomic_swap(T)(T* ptr, T val); ++ ++// This intrinsic adds delta to the value stored in memory at ptr. It yields ++// the original value at ptr. ++ ++pragma(intrinsic, "llvm.atomic.load.add.i#.p0i#") ++ T llvm_atomic_load_add(T)(shared const T* ptr, T val); ++ ++// This intrinsic subtracts delta to the value stored in memory at ptr. It ++// yields the original value at ptr. ++ ++pragma(intrinsic, "llvm.atomic.load.sub.i#.p0i#") ++ T llvm_atomic_load_sub(T)(T* ptr, T val); ++ ++// These intrinsics bitwise the operation (and, nand, or, xor) delta to the ++// value stored in memory at ptr. It yields the original value at ptr. ++ ++pragma(intrinsic, "llvm.atomic.load.and.i#.p0i#") ++ T llvm_atomic_load_and(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.nand.i#.p0i#") ++ T llvm_atomic_load_nand(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.or.i#.p0i#") ++ T llvm_atomic_load_or(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.xor.i#.p0i#") ++ T llvm_atomic_load_xor(T)(T* ptr, T val); ++ ++// These intrinsics takes the signed or unsigned minimum or maximum of delta ++// and the value stored in memory at ptr. It yields the original value at ptr. ++ ++pragma(intrinsic, "llvm.atomic.load.max.i#.p0i#") ++ T llvm_atomic_load_max(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.min.i#.p0i#") ++ T llvm_atomic_load_min(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.umax.i#.p0i#") ++ T llvm_atomic_load_umax(T)(T* ptr, T val); ++ ++pragma(intrinsic, "llvm.atomic.load.umin.i#.p0i#") ++ T llvm_atomic_load_umin(T)(T* ptr, T val); ++ ++ ++// ++// ARITHMETIC-WITH-OVERFLOW INTRINSICS ++// ++ ++struct OverflowRet(T) { ++ static assert(is(T : int), T.stringof ~ " is not an integer type!"); ++ T result; ++ bool overflow; ++} ++ ++// Signed and unsigned addition ++pragma(intrinsic, "llvm.sadd.with.overflow.i#") ++ OverflowRet!(T) llvm_sadd_with_overflow(T)(T lhs, T rhs); ++ ++pragma(intrinsic, "llvm.uadd.with.overflow.i#") ++ OverflowRet!(T) llvm_uadd_with_overflow(T)(T lhs, T rhs); ++ ++ ++// Signed and unsigned subtraction ++pragma(intrinsic, "llvm.ssub.with.overflow.i#") ++ OverflowRet!(T) llvm_ssub_with_overflow(T)(T lhs, T rhs); ++ ++pragma(intrinsic, "llvm.usub.with.overflow.i#") ++ OverflowRet!(T) llvm_usub_with_overflow(T)(T lhs, T rhs); ++ ++ ++// Signed and unsigned multiplication ++pragma(intrinsic, "llvm.smul.with.overflow.i#") ++ OverflowRet!(T) llvm_smul_with_overflow(T)(T lhs, T rhs); ++ ++/* Note: LLVM documentations says: ++ * Warning: 'llvm.umul.with.overflow' is badly broken. ++ * It is actively being fixed, but it should not currently be used! ++ * ++ * See: http://llvm.org/docs/LangRef.html#int_umul_overflow ++ */ ++//pragma(intrinsic, "llvm.umul.with.overflow.i#") ++// OverflowRet!(T) llvm_umul_with_overflow(T)(T lhs, T rhs); ++ ++ ++// ++// 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(); +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/ldc/llvmasm.di druntime/import/ldc/llvmasm.di +--- druntime-old/import/ldc/llvmasm.di 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/import/ldc/llvmasm.di 2010-09-30 22:10:37.000000000 +0400 +@@ -0,0 +1,17 @@ ++module ldc.llvmasm; ++ ++struct __asmtuple_t(T...) ++{ ++ T v; ++} ++ ++pragma(llvm_inline_asm) ++{ ++ void __asm( )(char[] asmcode, char[] constraints, ...); ++ T __asm(T)(char[] asmcode, char[] constraints, ...); ++ ++ template __asmtuple(T...) ++ { ++ __asmtuple_t!(T) __asmtuple(char[] asmcode, char[] constraints, ...); ++ } ++} +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/ldc/vararg.d druntime/import/ldc/vararg.d +--- druntime-old/import/ldc/vararg.d 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/import/ldc/vararg.d 2010-09-30 22:10:37.000000000 +0400 +@@ -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 ldc.Vararg; ++ ++// Check for the right compiler ++version(LDC) ++{ ++ // OK ++} ++else ++{ ++ static assert(false, "This module is only valid for LDC"); ++} ++ ++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; ++ // ldc 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; ++} +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/object.di druntime/import/object.di +--- druntime-old/import/object.di 2010-09-03 12:28:52.000000000 +0400 ++++ druntime/import/object.di 2010-10-05 12:47:24.873150000 +0400 +@@ -130,7 +130,7 @@ Interface[] interfaces; TypeInfo_Class base; void* destructor; @@ -528,7 +528,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. uint m_flags; // 1: // is IUnknown or is derived from IUnknown // 2: // has no possible pointers into GC memory -@@ -140,7 +140,7 @@ +@@ -140,7 +140,7 @@ // 32: // has typeinfo member void* deallocator; OffsetTypeInfo[] m_offTi; @@ -537,7 +537,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. const(MemberInfo[]) function(string) xgetMembers; static TypeInfo_Class find(in char[] classname); -@@ -179,7 +179,7 @@ +@@ -179,7 +179,7 @@ class TypeInfo_Const : TypeInfo { @@ -546,7 +546,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } class TypeInfo_Invariant : TypeInfo_Const -@@ -288,7 +288,6 @@ +@@ -288,7 +288,6 @@ interface TraceInfo { int opApply(scope int delegate(ref char[])); @@ -554,10 +554,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } string msg; -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/import/std/intrinsic.di ldc/druntime/import/std/intrinsic.di ---- v2.049/src/druntime/import/std/intrinsic.di 2010-08-05 05:39:08.000000000 +0400 -+++ ldc/druntime/import/std/intrinsic.di 1970-01-01 03:00:00.000000000 +0300 -@@ -1,176 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/import/std/intrinsic.di druntime/import/std/intrinsic.di +--- druntime-old/import/std/intrinsic.di 2010-08-05 05:39:08.000000000 +0400 ++++ druntime/import/std/intrinsic.di 1970-01-01 03:00:00.000000000 +0300 +@@ -1,176 +0,0 @@ -/** - * These functions are built-in intrinsics to the compiler. - * @@ -734,10 +734,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - * ditto - */ -nothrow uint outpl( uint port_address, uint value ); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/core/atomic.d ldc/druntime/src/core/atomic.d ---- v2.049/src/druntime/src/core/atomic.d 2010-09-03 12:28:52.000000000 +0400 -+++ ldc/druntime/src/core/atomic.d 2010-10-05 15:55:10.893150001 +0400 -@@ -89,6 +89,117 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/core/atomic.d druntime/src/core/atomic.d +--- druntime-old/src/core/atomic.d 2010-09-03 12:28:52.000000000 +0400 ++++ druntime/src/core/atomic.d 2010-10-05 15:55:10.893150001 +0400 +@@ -89,6 +89,117 @@ return false; } } @@ -855,7 +855,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. else version( AsmX86_32 ) { T atomicOp(string op, T, V1)( ref shared T val, V1 mod ) -@@ -396,6 +507,12 @@ +@@ -396,6 +507,12 @@ } } } @@ -868,10 +868,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. else version( AsmX86_64 ) { T atomicOp(string op, T, V1)( ref shared T val, V1 mod ) -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/gc/gc.d ldc/druntime/src/gc/gc.d ---- v2.049/src/druntime/src/gc/gc.d 2010-08-05 05:39:08.000000000 +0400 -+++ ldc/druntime/src/gc/gc.d 2010-10-04 16:54:06.837685001 +0400 -@@ -100,7 +100,7 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/gc/gc.d druntime/src/gc/gc.d +--- druntime-old/src/gc/gc.d 2010-08-05 05:39:08.000000000 +0400 ++++ druntime/src/gc/gc.d 2010-10-04 16:54:06.837685001 +0400 +@@ -100,7 +100,7 @@ version (GCCLASS) { void* p; ClassInfo ci = GC.classinfo; @@ -880,10 +880,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. p = malloc(ci.init.length); (cast(byte*)p)[0 .. ci.init.length] = ci.init[]; _gc = cast(GC)p; -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/gc/gcbits.d ldc/druntime/src/gc/gcbits.d ---- v2.049/src/druntime/src/gc/gcbits.d 2010-08-08 04:10:24.000000000 +0400 -+++ ldc/druntime/src/gc/gcbits.d 2010-10-01 20:49:51.268892001 +0400 -@@ -26,6 +26,10 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/gc/gcbits.d druntime/src/gc/gcbits.d +--- druntime-old/src/gc/gcbits.d 2010-08-08 04:10:24.000000000 +0400 ++++ druntime/src/gc/gcbits.d 2010-10-01 20:49:51.268892001 +0400 +@@ -26,6 +26,10 @@ { version = bitops; } @@ -894,10 +894,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. else version (GNU) { // use the unoptimized version -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/gc/gcx.d ldc/druntime/src/gc/gcx.d ---- v2.049/src/druntime/src/gc/gcx.d 2010-08-27 01:23:26.000000000 +0400 -+++ ldc/druntime/src/gc/gcx.d 2010-10-07 22:27:41.879253001 +0400 -@@ -1464,7 +1464,8 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/gc/gcx.d druntime/src/gc/gcx.d +--- druntime-old/src/gc/gcx.d 2010-08-27 01:23:26.000000000 +0400 ++++ druntime/src/gc/gcx.d 2010-10-07 22:27:41.879253001 +0400 +@@ -1464,7 +1464,8 @@ void initialize() @@ -907,7 +907,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. (cast(byte*)&this)[0 .. Gcx.sizeof] = 0; stackBottom = cast(char*)&dummy; -@@ -2200,7 +2201,7 @@ +@@ -2200,7 +2201,7 @@ if ((cast(size_t)p & ~(PAGESIZE-1)) == pcache) continue; @@ -916,7 +916,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. if (pool) { size_t offset = cast(size_t)(p - pool.baseAddr); -@@ -2270,80 +2271,129 @@ +@@ -2270,80 +2271,129 @@ __builtin_unwind_init(); sp = & sp; } @@ -1114,7 +1114,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. return result; } -@@ -2357,7 +2407,7 @@ +@@ -2357,7 +2407,7 @@ Pool* pool; debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n"); @@ -1123,10 +1123,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. thread_suspendAll(); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/object_.d ldc/druntime/src/object_.d ---- v2.049/src/druntime/src/object_.d 2010-09-03 12:28:52.000000000 +0400 -+++ ldc/druntime/src/object_.d 2010-10-05 14:50:34.733150002 +0400 -@@ -1073,7 +1073,7 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/object_.d druntime/src/object_.d +--- druntime-old/src/object_.d 2010-09-03 12:28:52.000000000 +0400 ++++ druntime/src/object_.d 2010-10-05 14:50:34.733150002 +0400 +@@ -1073,7 +1073,7 @@ abstract class MemberInfo { @@ -1135,7 +1135,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } class MemberInfo_field : MemberInfo -@@ -1663,7 +1663,6 @@ +@@ -1663,7 +1663,6 @@ { int len = 0; ModuleReference *mr; @@ -1143,7 +1143,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. for (mr = _Dmodule_ref; mr; mr = mr.next) len++; _moduleinfo_array = new ModuleInfo*[len]; -@@ -1802,7 +1801,10 @@ +@@ -1802,7 +1801,10 @@ { debug(PRINTF) printf("_moduleTlsCtor()\n"); @@ -1155,7 +1155,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. auto flags = cast(ubyte[])p[0 .. _moduleinfo_array.length]; flags[] = 0; -@@ -2025,7 +2027,6 @@ +@@ -2025,7 +2027,6 @@ _d_monitor_create(h); m = getMonitor(h); } @@ -1163,7 +1163,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. IMonitor i = m.impl; if (i is null) -@@ -2124,7 +2125,7 @@ +@@ -2124,7 +2125,7 @@ size_t _aaLen(void* p); void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...); void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...); @@ -1172,10 +1172,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. void _aaDel(void* p, TypeInfo keyti, ...); void[] _aaValues(void* p, size_t keysize, size_t valuesize); void[] _aaKeys(void* p, size_t keysize, size_t valuesize); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/adi.d ldc/druntime/src/rt/adi.d ---- v2.049/src/druntime/src/rt/adi.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/adi.d 2010-10-07 14:32:52.911253001 +0400 -@@ -35,6 +35,14 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/adi.d druntime/src/rt/adi.d +--- druntime-old/src/rt/adi.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/adi.d 2010-10-07 14:32:52.911253001 +0400 +@@ -35,6 +35,14 @@ extern (C) void gc_free( void* p ); } @@ -1190,7 +1190,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. struct Array { -@@ -48,7 +56,7 @@ +@@ -48,7 +56,7 @@ * reversed. */ @@ -1199,7 +1199,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { if (a.length > 1) { -@@ -108,7 +116,7 @@ +@@ -108,7 +116,7 @@ hi = hi - 1 + (stridehi - stridelo); } } @@ -1208,7 +1208,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } unittest -@@ -143,7 +151,7 @@ +@@ -143,7 +151,7 @@ * reversed. */ @@ -1217,7 +1217,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { if (a.length > 1) { -@@ -201,7 +209,7 @@ +@@ -201,7 +209,7 @@ hi = hi - 1 + (stridehi - stridelo); } } @@ -1226,7 +1226,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } unittest -@@ -225,10 +233,10 @@ +@@ -225,10 +233,10 @@ * Support for array.reverse property. */ @@ -1239,7 +1239,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } body { -@@ -243,10 +251,10 @@ +@@ -243,10 +251,10 @@ tmp = buffer.ptr; if (szelem > 16) { @@ -1253,7 +1253,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } for (; lo < hi; lo += szelem, hi -= szelem) -@@ -267,7 +275,7 @@ +@@ -267,7 +275,7 @@ //gc_free(tmp); } } @@ -1262,7 +1262,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } unittest -@@ -311,7 +319,7 @@ +@@ -311,7 +319,7 @@ * Sort array of chars. */ @@ -1271,7 +1271,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { if (a.length > 1) { -@@ -326,14 +334,14 @@ +@@ -326,14 +334,14 @@ } delete da; } @@ -1288,7 +1288,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { if (a.length > 1) { -@@ -348,7 +356,7 @@ +@@ -348,7 +356,7 @@ } delete da; } @@ -1297,7 +1297,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } /*************************************** -@@ -358,7 +366,7 @@ +@@ -358,7 +366,7 @@ * 0 not equal */ @@ -1306,7 +1306,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); if (a1.length != a2.length) -@@ -379,7 +387,7 @@ +@@ -379,7 +387,7 @@ return 1; // equal } @@ -1315,7 +1315,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); if (a1.length != a2.length) -@@ -405,7 +413,7 @@ +@@ -405,7 +413,7 @@ * Support for array compare test. */ @@ -1324,7 +1324,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { debug(adi) printf("adCmp()\n"); auto len = a1.length; -@@ -435,7 +443,7 @@ +@@ -435,7 +443,7 @@ return (a1.length > a2.length) ? 1 : -1; } @@ -1333,7 +1333,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); return ti.compare(&a1, &a2); -@@ -461,9 +469,9 @@ +@@ -461,9 +469,9 @@ * Support for array compare test. */ @@ -1345,7 +1345,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { asm { naked ; -@@ -569,8 +577,8 @@ +@@ -569,8 +577,8 @@ ret ; } @@ -1356,169 +1356,169 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { int len; int c; -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayInit.d ldc/druntime/src/rt/arrayInit.d ---- v2.049/src/druntime/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/src/rt/arrayInit.d 2010-10-03 20:41:52.223624001 +0400 -@@ -0,0 +1,155 @@ -+private import ldc.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_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_cfloat(cfloat* a, size_t n, cfloat v) -+{ -+ auto p = a; -+ auto end = a+n; -+ while (p !is end) -+ *p++ = v; -+} -+ -+void _d_array_init_cdouble(cdouble* a, size_t n, cdouble v) -+{ -+ auto p = a; -+ auto end = a+n; -+ while (p !is end) -+ *p++ = v; -+} -+ -+void _d_array_init_creal(creal* a, size_t n, creal 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; -+ } -+} -+ -+/* -+void _d_array_init(TypeInfo ti, void* a) -+{ -+ auto initializer = ti.next.init(); -+ auto isize = initializer.length; -+ auto q = initializer.ptr; -+ -+ 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); -+ } -+ } -+}*/ -+ -+// 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*elemsz) % newelemsz) { -+ throw new Exception("Bad array cast"); -+ } -+ return (len*elemsz)/newelemsz; -+} -+ -+// slice copy when assertions are enabled -+void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen) -+{ -+ assert(dst); -+ assert(src); -+ if (dstlen != srclen) -+ throw new Exception("lengths don't match for array copy"); -+ else if (dst+dstlen <= src || src+srclen <= dst) -+ llvm_memcpy(dst, src, dstlen, 0); -+ else -+ throw new Exception("overlapping array copy"); -+} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayassign.d ldc/druntime/src/rt/arrayassign.d ---- v2.049/src/druntime/src/rt/arrayassign.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arrayassign.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,186 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayInit.d druntime/src/rt/arrayInit.d +--- druntime-old/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/src/rt/arrayInit.d 2010-10-03 20:41:52.223624001 +0400 +@@ -0,0 +1,155 @@ ++private import ldc.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_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_cfloat(cfloat* a, size_t n, cfloat v) ++{ ++ auto p = a; ++ auto end = a+n; ++ while (p !is end) ++ *p++ = v; ++} ++ ++void _d_array_init_cdouble(cdouble* a, size_t n, cdouble v) ++{ ++ auto p = a; ++ auto end = a+n; ++ while (p !is end) ++ *p++ = v; ++} ++ ++void _d_array_init_creal(creal* a, size_t n, creal 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; ++ } ++} ++ ++/* ++void _d_array_init(TypeInfo ti, void* a) ++{ ++ auto initializer = ti.next.init(); ++ auto isize = initializer.length; ++ auto q = initializer.ptr; ++ ++ 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); ++ } ++ } ++}*/ ++ ++// 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*elemsz) % newelemsz) { ++ throw new Exception("Bad array cast"); ++ } ++ return (len*elemsz)/newelemsz; ++} ++ ++// slice copy when assertions are enabled ++void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t srclen) ++{ ++ assert(dst); ++ assert(src); ++ if (dstlen != srclen) ++ throw new Exception("lengths don't match for array copy"); ++ else if (dst+dstlen <= src || src+srclen <= dst) ++ llvm_memcpy(dst, src, dstlen, 0); ++ else ++ throw new Exception("overlapping array copy"); ++} +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayassign.d druntime/src/rt/arrayassign.d +--- druntime-old/src/rt/arrayassign.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arrayassign.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,186 +0,0 @@ -/** - * Implementation of array assignment support routines. - * @@ -1705,10 +1705,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - return pstart; -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arraybyte.d ldc/druntime/src/rt/arraybyte.d ---- v2.049/src/druntime/src/rt/arraybyte.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arraybyte.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,1893 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arraybyte.d druntime/src/rt/arraybyte.d +--- druntime-old/src/rt/arraybyte.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arraybyte.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,1893 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for char, byte, and - * ubyte ('a', 'g' and 'h' suffixes). @@ -3602,10 +3602,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arraycast.d ldc/druntime/src/rt/arraycast.d ---- v2.049/src/druntime/src/rt/arraycast.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arraycast.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,94 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arraycast.d druntime/src/rt/arraycast.d +--- druntime-old/src/rt/arraycast.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arraycast.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,94 +0,0 @@ -/** - * Implementation of array cast support routines. - * @@ -3700,10 +3700,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. -} - -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arraycat.d ldc/druntime/src/rt/arraycat.d ---- v2.049/src/druntime/src/rt/arraycat.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arraycat.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,42 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arraycat.d druntime/src/rt/arraycat.d +--- druntime-old/src/rt/arraycat.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arraycat.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,42 +0,0 @@ -/** - * Implementation of array copy support routines. - * @@ -3746,10 +3746,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - return to; -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arraydouble.d ldc/druntime/src/rt/arraydouble.d ---- v2.049/src/druntime/src/rt/arraydouble.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arraydouble.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,1720 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arraydouble.d druntime/src/rt/arraydouble.d +--- druntime-old/src/rt/arraydouble.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arraydouble.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,1720 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for double. - * @@ -5470,10 +5470,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayfloat.d ldc/druntime/src/rt/arrayfloat.d ---- v2.049/src/druntime/src/rt/arrayfloat.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arrayfloat.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,1435 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayfloat.d druntime/src/rt/arrayfloat.d +--- druntime-old/src/rt/arrayfloat.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arrayfloat.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,1435 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for float. - * @@ -6909,10 +6909,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayint.d ldc/druntime/src/rt/arrayint.d ---- v2.049/src/druntime/src/rt/arrayint.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arrayint.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,2430 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayint.d druntime/src/rt/arrayint.d +--- druntime-old/src/rt/arrayint.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arrayint.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,2430 +0,0 @@ -/** - * Contains MMX versions of certain operations for dchar, int, and uint ('w', - * 'i' and 'k' suffixes). @@ -9343,10 +9343,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayreal.d ldc/druntime/src/rt/arrayreal.d ---- v2.049/src/druntime/src/rt/arrayreal.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arrayreal.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,241 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayreal.d druntime/src/rt/arrayreal.d +--- druntime-old/src/rt/arrayreal.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arrayreal.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,241 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for real. - * @@ -9588,10 +9588,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/arrayshort.d ldc/druntime/src/rt/arrayshort.d ---- v2.049/src/druntime/src/rt/arrayshort.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/arrayshort.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,2303 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/arrayshort.d druntime/src/rt/arrayshort.d +--- druntime-old/src/rt/arrayshort.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/arrayshort.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,2303 +0,0 @@ -/** - * Contains SSE2 and MMX versions of certain operations for wchar, short, - * and ushort ('u', 's' and 't' suffixes). @@ -11895,10 +11895,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/deh.c ldc/druntime/src/rt/deh.c ---- v2.049/src/druntime/src/rt/deh.c 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/deh.c 1970-01-01 03:00:00.000000000 +0300 -@@ -1,734 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/deh.c druntime/src/rt/deh.c +--- druntime-old/src/rt/deh.c 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/deh.c 1970-01-01 03:00:00.000000000 +0300 +@@ -1,734 +0,0 @@ -/** - * Implementation of exception handling support routines for Windows. - * @@ -12633,10 +12633,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - - -#endif -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/deh2.d ldc/druntime/src/rt/deh2.d ---- v2.049/src/druntime/src/rt/deh2.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/deh2.d 1970-01-01 03:00:00.000000000 +0300 -@@ -1,322 +0,0 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/deh2.d druntime/src/rt/deh2.d +--- druntime-old/src/rt/deh2.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/deh2.d 1970-01-01 03:00:00.000000000 +0300 +@@ -1,322 +0,0 @@ -/** - * Implementation of exception handling support routines for Posix. - * @@ -12959,442 +12959,442 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. - } - } -} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/eh.d ldc/druntime/src/rt/eh.d ---- v2.049/src/druntime/src/rt/eh.d 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/src/rt/eh.d 2010-10-03 18:29:58.099624002 +0400 -@@ -0,0 +1,428 @@ -+/** -+ * This module contains functions and structures required for -+ * exception handling. -+ */ -+module eh; -+ -+private import core.stdc.stdio; -+private import core.stdc.stdlib; -+private import rt.util.console; -+private import ldc.cstdarg; -+ -+// debug = EH_personality; -+// debug = EH_personality_verbose; -+ -+// current EH implementation works on x86 -+// if it has a working unwind runtime -+version(X86) { -+ version(linux) version=X86_UNWIND; -+ version(darwin) version=X86_UNWIND; -+ version(solaris) version=X86_UNWIND; -+} -+version(X86_64) { -+ version(linux) version=X86_UNWIND; -+ version(darwin) version=X86_UNWIND; -+ version(solaris) version=X86_UNWIND; -+} -+ -+//version = HP_LIBUNWIND; -+ -+// D runtime functions -+extern(C) { -+ int _d_isbaseof(ClassInfo oc, ClassInfo c); -+} -+ -+// libunwind headers -+extern(C) -+{ -+ enum _Unwind_Reason_Code : int -+ { -+ 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 : int -+ { -+ SEARCH_PHASE = 1, -+ CLEANUP_PHASE = 2, -+ HANDLER_FRAME = 4, -+ FORCE_UNWIND = 8 -+ } -+ -+ alias void* _Unwind_Context_Ptr; -+ -+ alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn; -+ -+ struct _Unwind_Exception -+ { -+ ulong exception_class; -+ _Unwind_Exception_Cleanup_Fn exception_cleanup; -+ ptrdiff_t private_1; -+ ptrdiff_t private_2; -+ } -+ -+// interface to HP's libunwind from http://www.nongnu.org/libunwind/ -+version(HP_LIBUNWIND) -+{ -+ void __libunwind_Unwind_Resume(_Unwind_Exception *); -+ _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); -+ ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr -+ context); -+ ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); -+ ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, -+ ptrdiff_t new_value); -+ ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, -+ ptrdiff_t new_value); -+ ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); -+ -+ alias __libunwind_Unwind_Resume _Unwind_Resume; -+ alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; -+ alias __libunwind_Unwind_GetLanguageSpecificData -+ _Unwind_GetLanguageSpecificData; -+ alias __libunwind_Unwind_GetIP _Unwind_GetIP; -+ alias __libunwind_Unwind_SetIP _Unwind_SetIP; -+ alias __libunwind_Unwind_SetGR _Unwind_SetGR; -+ alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; -+} -+else version(X86_UNWIND) -+{ -+ void _Unwind_Resume(_Unwind_Exception*); -+ _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); -+ ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); -+ ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context); -+ ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); -+ ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, -+ ptrdiff_t new_value); -+ ptrdiff_t _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; -+ } -+} -+ -+} -+ -+// error and exit -+extern(C) private void fatalerror(in char* format, ...) -+{ -+ va_list args; -+ va_start(args, format); -+ printf("Fatal error in EH code: "); -+ vprintf(format, args); -+ printf("\n"); -+ abort(); -+} -+ -+ -+// helpers for reading certain DWARF data -+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) -+ fatalerror("tried to read uleb128 that exceeded size of size_t"); -+ } -+ // read last -+ if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) -+ fatalerror("Fatal error in EH code: 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) -+ fatalerror("tried to read sleb128 that exceeded size of size_t"); -+ } -+ // read last -+ if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) -+ fatalerror("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 unwind specific implementation of personality function -+// and helpers -+// -+version(X86_UNWIND) -+{ -+ -+// 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) -+{ -+ debug(EH_personality_verbose) printf("entering personality function. context: %p\n", 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); -+ if (callsite_table is null) -+ return _Unwind_Reason_Code.CONTINUE_UNWIND; -+ -+ /* -+ 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 -+ ptrdiff_t ip = _Unwind_GetIP(context) - 1; -+ -+ // address block_start is relative to -+ ptrdiff_t region_start = _Unwind_GetRegionStart(context); -+ -+ // table entries -+ uint block_start_offset, block_size; -+ ptrdiff_t 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("ip=%llx %d %d %llx\n", ip, 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 -+ if(!(ti_offset >= 0)) -+ fatalerror("Filter actions are unsupported"); -+ -+ // zero means cleanup, which we require to be the last action -+ if(ti_offset == 0) { -+ if(!(next_action_offset == 0)) -+ fatalerror("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; -+ } -+ -+ fatalerror("reached unreachable"); -+ return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; -+} -+ -+// These are the register numbers for SetGR that -+// llvm's eh.exception and eh.selector intrinsics -+// will pick up. -+// Hints for these can be found by looking at the -+// EH_RETURN_DATA_REGNO macro in GCC, careful testing -+// is required though. -+version (X86_64) -+{ -+ private int eh_exception_regno = 0; -+ private int eh_selector_regno = 1; -+} else { -+ 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, ptrdiff_t 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.CLEANUP_PHASE) -+ { -+ debug(EH_personality) printf("Setting switch value to: %d!\n", switchval); -+ _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)cast(void*)(exception_struct.exception_object)); -+ _Unwind_SetGR(context, eh_selector_regno, cast(ptrdiff_t)switchval); -+ _Unwind_SetIP(context, landing_pad); -+ return _Unwind_Reason_Code.INSTALL_CONTEXT; -+ } -+ -+ fatalerror("reached unreachable"); -+ return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; -+} -+ -+private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ptrdiff_t 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(ptrdiff_t)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); -+ if (data is null) -+ { -+ //printf("language specific data was null\n"); -+ callsite = null; -+ action = null; -+ ci = null; -+ return; -+ } -+ -+ //TODO: Do proper DWARF reading here -+ if(*data++ != 0xff) -+ fatalerror("DWARF header has unexpected format 1"); -+ -+ if(*data++ != 0x00) -+ fatalerror("DWARF header has unexpected format 2"); -+ size_t cioffset; -+ data = get_uleb128(data, cioffset); -+ ci = cast(ClassInfo*)(data + cioffset); -+ -+ if(*data++ != 0x03) -+ fatalerror("DWARF header has unexpected format 3"); -+ 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 = *cast(ulong*)_d_exception_class.ptr; -+ 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); -+} -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/lifetime.d ldc/druntime/src/rt/lifetime.d ---- v2.049/src/druntime/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/lifetime.d 2010-10-07 22:03:51.471253002 +0400 -@@ -81,6 +81,28 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/eh.d druntime/src/rt/eh.d +--- druntime-old/src/rt/eh.d 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/src/rt/eh.d 2010-10-03 18:29:58.099624002 +0400 +@@ -0,0 +1,428 @@ ++/** ++ * This module contains functions and structures required for ++ * exception handling. ++ */ ++module eh; ++ ++private import core.stdc.stdio; ++private import core.stdc.stdlib; ++private import rt.util.console; ++private import ldc.cstdarg; ++ ++// debug = EH_personality; ++// debug = EH_personality_verbose; ++ ++// current EH implementation works on x86 ++// if it has a working unwind runtime ++version(X86) { ++ version(linux) version=X86_UNWIND; ++ version(darwin) version=X86_UNWIND; ++ version(solaris) version=X86_UNWIND; ++} ++version(X86_64) { ++ version(linux) version=X86_UNWIND; ++ version(darwin) version=X86_UNWIND; ++ version(solaris) version=X86_UNWIND; ++} ++ ++//version = HP_LIBUNWIND; ++ ++// D runtime functions ++extern(C) { ++ int _d_isbaseof(ClassInfo oc, ClassInfo c); ++} ++ ++// libunwind headers ++extern(C) ++{ ++ enum _Unwind_Reason_Code : int ++ { ++ 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 : int ++ { ++ SEARCH_PHASE = 1, ++ CLEANUP_PHASE = 2, ++ HANDLER_FRAME = 4, ++ FORCE_UNWIND = 8 ++ } ++ ++ alias void* _Unwind_Context_Ptr; ++ ++ alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn; ++ ++ struct _Unwind_Exception ++ { ++ ulong exception_class; ++ _Unwind_Exception_Cleanup_Fn exception_cleanup; ++ ptrdiff_t private_1; ++ ptrdiff_t private_2; ++ } ++ ++// interface to HP's libunwind from http://www.nongnu.org/libunwind/ ++version(HP_LIBUNWIND) ++{ ++ void __libunwind_Unwind_Resume(_Unwind_Exception *); ++ _Unwind_Reason_Code __libunwind_Unwind_RaiseException(_Unwind_Exception *); ++ ptrdiff_t __libunwind_Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr ++ context); ++ ptrdiff_t __libunwind_Unwind_GetIP(_Unwind_Context_Ptr context); ++ ptrdiff_t __libunwind_Unwind_SetIP(_Unwind_Context_Ptr context, ++ ptrdiff_t new_value); ++ ptrdiff_t __libunwind_Unwind_SetGR(_Unwind_Context_Ptr context, int index, ++ ptrdiff_t new_value); ++ ptrdiff_t __libunwind_Unwind_GetRegionStart(_Unwind_Context_Ptr context); ++ ++ alias __libunwind_Unwind_Resume _Unwind_Resume; ++ alias __libunwind_Unwind_RaiseException _Unwind_RaiseException; ++ alias __libunwind_Unwind_GetLanguageSpecificData ++ _Unwind_GetLanguageSpecificData; ++ alias __libunwind_Unwind_GetIP _Unwind_GetIP; ++ alias __libunwind_Unwind_SetIP _Unwind_SetIP; ++ alias __libunwind_Unwind_SetGR _Unwind_SetGR; ++ alias __libunwind_Unwind_GetRegionStart _Unwind_GetRegionStart; ++} ++else version(X86_UNWIND) ++{ ++ void _Unwind_Resume(_Unwind_Exception*); ++ _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*); ++ ptrdiff_t _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context); ++ ptrdiff_t _Unwind_GetIP(_Unwind_Context_Ptr context); ++ ptrdiff_t _Unwind_SetIP(_Unwind_Context_Ptr context, ptrdiff_t new_value); ++ ptrdiff_t _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ++ ptrdiff_t new_value); ++ ptrdiff_t _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; ++ } ++} ++ ++} ++ ++// error and exit ++extern(C) private void fatalerror(in char* format, ...) ++{ ++ va_list args; ++ va_start(args, format); ++ printf("Fatal error in EH code: "); ++ vprintf(format, args); ++ printf("\n"); ++ abort(); ++} ++ ++ ++// helpers for reading certain DWARF data ++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) ++ fatalerror("tried to read uleb128 that exceeded size of size_t"); ++ } ++ // read last ++ if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) ++ fatalerror("Fatal error in EH code: 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) ++ fatalerror("tried to read sleb128 that exceeded size of size_t"); ++ } ++ // read last ++ if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize) ++ fatalerror("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 unwind specific implementation of personality function ++// and helpers ++// ++version(X86_UNWIND) ++{ ++ ++// 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) ++{ ++ debug(EH_personality_verbose) printf("entering personality function. context: %p\n", 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); ++ if (callsite_table is null) ++ return _Unwind_Reason_Code.CONTINUE_UNWIND; ++ ++ /* ++ 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 ++ ptrdiff_t ip = _Unwind_GetIP(context) - 1; ++ ++ // address block_start is relative to ++ ptrdiff_t region_start = _Unwind_GetRegionStart(context); ++ ++ // table entries ++ uint block_start_offset, block_size; ++ ptrdiff_t 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("ip=%llx %d %d %llx\n", ip, 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 ++ if(!(ti_offset >= 0)) ++ fatalerror("Filter actions are unsupported"); ++ ++ // zero means cleanup, which we require to be the last action ++ if(ti_offset == 0) { ++ if(!(next_action_offset == 0)) ++ fatalerror("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; ++ } ++ ++ fatalerror("reached unreachable"); ++ return _Unwind_Reason_Code.FATAL_PHASE1_ERROR; ++} ++ ++// These are the register numbers for SetGR that ++// llvm's eh.exception and eh.selector intrinsics ++// will pick up. ++// Hints for these can be found by looking at the ++// EH_RETURN_DATA_REGNO macro in GCC, careful testing ++// is required though. ++version (X86_64) ++{ ++ private int eh_exception_regno = 0; ++ private int eh_selector_regno = 1; ++} else { ++ 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, ptrdiff_t 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.CLEANUP_PHASE) ++ { ++ debug(EH_personality) printf("Setting switch value to: %d!\n", switchval); ++ _Unwind_SetGR(context, eh_exception_regno, cast(ptrdiff_t)cast(void*)(exception_struct.exception_object)); ++ _Unwind_SetGR(context, eh_selector_regno, cast(ptrdiff_t)switchval); ++ _Unwind_SetIP(context, landing_pad); ++ return _Unwind_Reason_Code.INSTALL_CONTEXT; ++ } ++ ++ fatalerror("reached unreachable"); ++ return _Unwind_Reason_Code.FATAL_PHASE2_ERROR; ++} ++ ++private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ptrdiff_t 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(ptrdiff_t)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); ++ if (data is null) ++ { ++ //printf("language specific data was null\n"); ++ callsite = null; ++ action = null; ++ ci = null; ++ return; ++ } ++ ++ //TODO: Do proper DWARF reading here ++ if(*data++ != 0xff) ++ fatalerror("DWARF header has unexpected format 1"); ++ ++ if(*data++ != 0x00) ++ fatalerror("DWARF header has unexpected format 2"); ++ size_t cioffset; ++ data = get_uleb128(data, cioffset); ++ ci = cast(ClassInfo*)(data + cioffset); ++ ++ if(*data++ != 0x03) ++ fatalerror("DWARF header has unexpected format 3"); ++ 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 = *cast(ulong*)_d_exception_class.ptr; ++ 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); ++} +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/lifetime.d druntime/src/rt/lifetime.d +--- druntime-old/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/lifetime.d 2010-10-08 14:55:56.581547002 +0400 +@@ -81,6 +81,28 @@ MAXSMALLSIZE = 256-SMALLPAD, MAXMEDSIZE = (PAGESIZE / 2) - MEDPAD } @@ -13423,7 +13423,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } -@@ -92,6 +114,13 @@ +@@ -92,6 +114,13 @@ return gc_malloc(sz); } @@ -13437,577 +13437,206 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. /** * -@@ -665,6 +694,249 @@ - onOutOfMemoryError(); - } - -+version (LDC) -+{ -+ -+/** -+ * Allocate a new array of length elements. -+ * ti is the type of the resulting array, or pointer to element. -+ * The resulting 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; -+ -+ size = length_adjust(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; -+} -+ -+/** -+ * As _d_newarrayT, but -+ * 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; -+ -+ size = length_adjust(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; -+} -+ -+/** -+ * As _d_newarrayT, but without initialization -+ */ -+extern (C) void* _d_newarrayvT(TypeInfo ti, size_t length) -+{ -+ void* p; -+ auto size = ti.next.tsize(); // array element size -+ -+ debug(PRINTF) printf("_d_newarrayvT(length = %u, size = %d)\n", length, size); -+ if (length == 0 || size == 0) -+ return null; -+ -+ size = length_adjust(size, length); -+ -+ p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); -+ debug(PRINTF) printf(" p = %p\n", p); -+ return p; -+} -+ -+/** -+ * Allocate a new array of arrays of arrays of arrays ... -+ * ti is the type of the resulting array. -+ * ndims is the number of nested arrays. -+ * dims it the array of dimensions, its size is ndims. -+ * The resulting array is initialized to 0 -+ */ -+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; -+} -+ -+ -+/** -+ * As _d_newarraymT, but -+ * for when the array has a non-zero initializer. -+ */ -+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; -+} -+ -+/** -+ * As _d_newarraymT, but without initialization -+ */ -+extern (C) void* _d_newarraymvT(TypeInfo ti, int ndims, size_t* dims) -+{ -+ void* result; -+ -+ debug(PRINTF) printf("_d_newarraymvT(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_newarrayvT(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; -+} -+ -+} else { -+ - /** - * Allocate a new array of length elements. +@@ -670,7 +699,7 @@ * ti is the type of the resulting array, or pointer to element. -@@ -884,6 +1156,7 @@ - return result; + * (For when the array is initialized to 0) + */ +-extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length) ++extern (C) void[] _d_newarrayT(TypeInfo ti, size_t length) + { + ulong result; + auto size = ti.next.tsize(); // array element size +@@ -702,7 +731,7 @@ + __setArrayAllocLength(info, size, isshared); + result = cast(ulong)length + (cast(ulong)cast(size_t)arrstart << 32); + } +- return result; ++ return *cast(void[]*)&result; + + Loverflow: + onOutOfMemoryError(); +@@ -711,7 +740,7 @@ + /** + * For when the array has a non-zero initializer. + */ +-extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length) ++extern (C) void[] _d_newarrayiT(TypeInfo ti, size_t length) + { + ulong result; + auto size = ti.next.tsize(); // array element size +@@ -764,7 +793,7 @@ + __setArrayAllocLength(info, size, isshared); + result = cast(ulong)length + (cast(ulong)cast(uint)arrstart << 32); + } +- return result; ++ return *cast(void[]*)&result; + + Loverflow: + onOutOfMemoryError(); +@@ -773,7 +802,7 @@ + /** + * + */ +-extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...) ++extern (C) void[] _d_newarraymT(TypeInfo ti, int ndims, ...) + { + ulong result; + +@@ -823,14 +852,14 @@ + } + va_end(q); + } +- return result; ++ return *cast(void[]*)&result; } -+} /** * -@@ -1042,6 +1315,175 @@ + */ +-extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...) ++extern (C) void[] _d_newarraymiT(TypeInfo ti, int ndims, ...) + { + ulong result; + +@@ -881,10 +910,9 @@ + } + va_end(q); } +- return result; ++ return *cast(void[]*)&result; } -+version (LDC) -+{ -+/** -+ * Resize dynamic arrays with 0 initializers. -+ */ -+extern (C) byte* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, byte* pdata) -+in -+{ -+ assert(ti); -+// This assert on array consistency may fail with casts or in unions. -+// This function still does something sensible even if plength && !pdata. -+// 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) -+ { -+ size_t newsize = length_adjust(sizeelem, newlength); -+ -+ 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; -+} -+ -+/** -+ * 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 -+{ -+// This assert on array consistency may fail with casts or in unions. -+// This function still does something sensible even if plength && !pdata. -+// 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) -+ { -+ size_t newsize = length_adjust(sizeelem, newlength); -+ 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; -+} -+ -+} else { // version (LDC) -+ - +- + /** + * + */ +@@ -1046,7 +1074,7 @@ /** * Resize dynamic arrays with 0 initializers. -@@ -1376,6 +1818,58 @@ + */ +-extern (C) byte[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p) ++extern (C) void[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p) + in + { + assert(ti); +@@ -1206,7 +1234,7 @@ + * initsize size of initializer + * ... initializer + */ +-extern (C) byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p) ++extern (C) void[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p) + in + { + assert(!p.length || p.data); +@@ -1376,12 +1404,11 @@ onOutOfMemoryError(); } -+} -+ +- + /** + * Append y[] to array pointed to by px + * size is size of each array element. + */ +-extern (C) long _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) ++extern (C) void[] _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) + { + // only optimize array append where ti is not a shared type + auto sizeelem = ti.next.tsize(); // array element size +@@ -1468,10 +1495,9 @@ + L1: + px.length = newlength; + memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem); +- return *cast(long*)px; ++ return *cast(void[]*)px; + } + +- + /** + * + */ +@@ -1552,21 +1578,36 @@ + return newcap; + } + +version (LDC) +{ + +/** + * Appends a single element to an array. + */ -+extern (C) byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) ++extern (C) void[] _d_arrayappendcT(TypeInfo ti, byte[] *x, byte *argp) +{ -+ auto x = cast(byte[]*)array; -+ 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 *)element; -+ -+ *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; ++ return _d_arrayappendT(ti, cast(Array*)x, argp[0..1]); +} + -+} // version (LDC) -+else -+{ - - /** - * Append y[] to array pointed to by px -@@ -1471,6 +1965,7 @@ - return *cast(long*)px; - } - -+} - - /** - * -@@ -1552,6 +2047,11 @@ - return newcap; - } - -+version (LDC) -+{ +} +else +{ /** * -@@ -1641,6 +2141,8 @@ + */ +-extern (C) long _d_arrayappendcT(TypeInfo ti, Array *x, ...) ++extern (C) void[] _d_arrayappendcT(TypeInfo ti, Array *x, ...) + { + byte *argp = cast(byte*)(&ti + 2); + return _d_arrayappendT(ti, x, argp[0..1]); + } + ++} + + /** + * Append dchar to char[] + */ +-extern (C) long _d_arrayappendcd(ref char[] x, dchar c) ++extern (C) void[] _d_arrayappendcd(ref char[] x, dchar c) + { + // c could encode into from 1 to 4 characters + char[4] buf = void; +@@ -1612,7 +1653,7 @@ + /** + * Append dchar to wchar[] + */ +-extern (C) long _d_arrayappendwd(ref wchar[] x, dchar c) ++extern (C) void[] _d_arrayappendwd(ref wchar[] x, dchar c) + { + // c could encode into from 1 to 2 w characters + wchar[2] buf = void; +@@ -1641,7 +1682,6 @@ return _d_arrayappendT(typeid(shared wchar[]), cast(Array *)&x, appendthis); } -+} -+ - +- /** * -@@ -1794,6 +2296,35 @@ + */ +@@ -1794,11 +1834,10 @@ void* ptr; } -+version (LDC) -+{ -+ -+/** -+ * -+ */ -+extern (C) void[] _adDupT(TypeInfo ti, void[] a) -+out (result) -+{ -+ auto sizeelem = ti.next.tsize(); // array element size -+ assert(memcmp(result.ptr, a.ptr, a.length * sizeelem) == 0); -+} -+body -+{ -+ void* ptr; -+ -+ if (a.length) -+ { -+ auto sizeelem = ti.next.tsize(); // array element size -+ auto size = a.length * sizeelem; -+ ptr = gc_malloc(size, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0); -+ memcpy(ptr, a.ptr, size); -+ } -+ return ptr[0 .. a.length]; -+} -+ -+} -+else -+{ - +- /** * -@@ -1822,6 +2353,8 @@ - return *cast(long*)(&r); + */ +-extern (C) long _adDupT(TypeInfo ti, Array2 a) ++extern (C) void[] _adDupT(TypeInfo ti, void[] a) + out (result) + { + auto sizeelem = ti.next.tsize(); // array element size +@@ -1819,7 +1858,7 @@ + r.length = a.length; + memcpy(r.ptr, a.ptr, size); + } +- return *cast(long*)(&r); ++ return *cast(void[]*)(&r); } -+} -+ - unittest - { -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/qsort.d ldc/druntime/src/rt/qsort.d ---- v2.049/src/druntime/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/qsort.d 2010-10-07 13:59:06.815253002 +0400 -@@ -44,7 +44,7 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/qsort.d druntime/src/rt/qsort.d +--- druntime-old/src/rt/qsort.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/qsort.d 2010-10-07 13:59:06.815253002 +0400 +@@ -44,7 +44,7 @@ structures. The default value is optimized for a high cost for compares. */ @@ -14016,7 +13645,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. { byte* base; byte*[40] stack; // stack -@@ -124,7 +124,7 @@ +@@ -124,7 +124,7 @@ limit = sp[1]; } else // else stack empty, all done @@ -14025,10 +13654,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } assert(0); } -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/qsort2.d ldc/druntime/src/rt/qsort2.d ---- v2.049/src/druntime/src/rt/qsort2.d 2010-08-05 05:39:06.000000000 +0400 -+++ ldc/druntime/src/rt/qsort2.d 2010-10-07 14:01:41.359253001 +0400 -@@ -31,14 +31,14 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/qsort2.d druntime/src/rt/qsort2.d +--- druntime-old/src/rt/qsort2.d 2010-08-05 05:39:06.000000000 +0400 ++++ druntime/src/rt/qsort2.d 2010-10-07 14:01:41.359253001 +0400 +@@ -31,14 +31,14 @@ return tiglobal.compare(p1, p2); } @@ -14045,10 +13674,10 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. } -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/rt/trace.d ldc/druntime/src/rt/trace.d ---- v2.049/src/druntime/src/rt/trace.d 2010-08-07 09:46:06.000000000 +0400 -+++ ldc/druntime/src/rt/trace.d 2010-10-01 21:01:58.444892002 +0400 -@@ -855,7 +855,7 @@ +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/rt/trace.d druntime/src/rt/trace.d +--- druntime-old/src/rt/trace.d 2010-08-07 09:46:06.000000000 +0400 ++++ druntime/src/rt/trace.d 2010-10-01 21:01:58.444892002 +0400 +@@ -855,7 +855,7 @@ version (OSX) { // 16 byte align stack asm @@ -14057,7 +13686,7 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. pushad ; sub ESP,12 ; } -@@ -870,7 +870,7 @@ +@@ -870,7 +870,7 @@ else { asm @@ -14066,219 +13695,219 @@ diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch. pushad ; } trace_epi(); -diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- v2.049/src/druntime/src/std/intrinsic.d ldc/druntime/src/std/intrinsic.d ---- v2.049/src/druntime/src/std/intrinsic.d 1970-01-01 03:00:00.000000000 +0300 -+++ ldc/druntime/src/std/intrinsic.d 2010-10-03 20:07:21.183624002 +0400 -@@ -0,0 +1,212 @@ -+/* -+ * D phobos intrinsics for LDC -+ * -+ * From GDC ... public domain! -+ */ -+module std.intrinsic; -+ -+// Check for the right compiler -+version(LDC) -+{ -+ // OK -+} -+else -+{ -+ static assert(false, "This module is only valid for LDC"); -+} -+ -+/** -+ * Scans the bits in v starting with bit 0, looking -+ * for the first set bit. -+ * Returns: -+ * The bit number of the first bit set. -+ * The return value is undefined if v is zero. -+ */ -+nothrow 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 -+} -+ -+/** -+ * Scans the bits in v from the most significant bit -+ * to the least significant bit, looking -+ * for the first set bit. -+ * Returns: -+ * The bit number of the first bit set. -+ * The return value is undefined if v is zero. -+ * Example: -+ * --- -+ * import std.intrinsic; -+ * -+ * int main() -+ * { -+ * uint v; -+ * int x; -+ * -+ * v = 0x21; -+ * x = bsf(v); -+ * printf("bsf(x%x) = %d\n", v, x); -+ * x = bsr(v); -+ * printf("bsr(x%x) = %d\n", v, x); -+ * return 0; -+ * } -+ * --- -+ * Output: -+ * bsf(x21) = 0
-+ * bsr(x21) = 5 -+ */ -+nothrow 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 -+} -+ -+ -+/** -+ * Tests the bit. -+ */ -+nothrow int bt(uint *p, uint bitnum) -+{ -+ return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ; -+} -+ -+ -+/** -+ * Tests and complements the bit. -+ */ -+nothrow 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; -+} -+ -+ -+/** -+ * Tests and resets (sets to 0) the bit. -+ */ -+nothrow 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; -+} -+ -+ -+/** -+ * Tests and sets the bit. -+ * Params: -+ * p = a non-NULL pointer to an array of uints. -+ * index = a bit number, starting with bit 0 of p[0], -+ * and progressing. It addresses bits like the expression: -+--- -+p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) -+--- -+ * Returns: -+ * A non-zero value if the bit was set, and a zero -+ * if it was clear. -+ * -+ * Example: -+ * --- -+import std.intrinsic; -+ -+int main() -+{ -+ uint array[2]; -+ -+ array[0] = 2; -+ array[1] = 0x100; -+ -+ printf("btc(array, 35) = %d\n", btc(array, 35)); -+ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); -+ -+ printf("btc(array, 35) = %d\n", btc(array, 35)); -+ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); -+ -+ printf("bts(array, 35) = %d\n", bts(array, 35)); -+ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); -+ -+ printf("btr(array, 35) = %d\n", btr(array, 35)); -+ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); -+ -+ printf("bt(array, 1) = %d\n", bt(array, 1)); -+ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); -+ -+ return 0; -+} -+ * --- -+ * Output: -+
-+btc(array, 35) = 0
-+array = [0]:x2, [1]:x108
-+btc(array, 35) = -1
-+array = [0]:x2, [1]:x100
-+bts(array, 35) = 0
-+array = [0]:x2, [1]:x108
-+btr(array, 35) = -1
-+array = [0]:x2, [1]:x100
-+bt(array, 1) = -1
-+array = [0]:x2, [1]:x100
-+
-+ */ -+nothrow 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; -+} -+ -+/** -+ * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes -+ * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 -+ * becomes byte 0. -+ */ -+pragma(intrinsic, "llvm.bswap.i32") -+ uint bswap(uint val); -+ -+/** -+ * Reads I/O port at port_address. -+ */ -+ubyte inp(uint p) { throw new Exception("inp intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+ushort inpw(uint p) { throw new Exception("inpw intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+uint inpl(uint p) { throw new Exception("inpl intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+ubyte outp(uint p, ubyte v) { throw new Exception("outp intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+ushort outpw(uint p, ushort v) { throw new Exception("outpw intrinsic not yet implemented"); } -+ -+/** -+ * ditto -+ */ -+uint outpl(uint p, uint v) { throw new Exception("outpl intrinsic not yet implemented"); } +diff -U 3 -H -d -r -N -x '*.mak' -x tk -x backend -x debug -x release -x '*_pch.h' -x Makefile -x '*.rej' -x '*~' -x '*.log' -x .svn -x '*pro.user' -x .directory -x cmake_install -x CMakeFiles -x .preprocessed.tmp -x 'Makefile.*' -x '*.orig' -- druntime-old/src/std/intrinsic.d druntime/src/std/intrinsic.d +--- druntime-old/src/std/intrinsic.d 1970-01-01 03:00:00.000000000 +0300 ++++ druntime/src/std/intrinsic.d 2010-10-03 20:07:21.183624002 +0400 +@@ -0,0 +1,212 @@ ++/* ++ * D phobos intrinsics for LDC ++ * ++ * From GDC ... public domain! ++ */ ++module std.intrinsic; ++ ++// Check for the right compiler ++version(LDC) ++{ ++ // OK ++} ++else ++{ ++ static assert(false, "This module is only valid for LDC"); ++} ++ ++/** ++ * Scans the bits in v starting with bit 0, looking ++ * for the first set bit. ++ * Returns: ++ * The bit number of the first bit set. ++ * The return value is undefined if v is zero. ++ */ ++nothrow 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 ++} ++ ++/** ++ * Scans the bits in v from the most significant bit ++ * to the least significant bit, looking ++ * for the first set bit. ++ * Returns: ++ * The bit number of the first bit set. ++ * The return value is undefined if v is zero. ++ * Example: ++ * --- ++ * import std.intrinsic; ++ * ++ * int main() ++ * { ++ * uint v; ++ * int x; ++ * ++ * v = 0x21; ++ * x = bsf(v); ++ * printf("bsf(x%x) = %d\n", v, x); ++ * x = bsr(v); ++ * printf("bsr(x%x) = %d\n", v, x); ++ * return 0; ++ * } ++ * --- ++ * Output: ++ * bsf(x21) = 0
++ * bsr(x21) = 5 ++ */ ++nothrow 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 ++} ++ ++ ++/** ++ * Tests the bit. ++ */ ++nothrow int bt(uint *p, uint bitnum) ++{ ++ return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ; ++} ++ ++ ++/** ++ * Tests and complements the bit. ++ */ ++nothrow 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; ++} ++ ++ ++/** ++ * Tests and resets (sets to 0) the bit. ++ */ ++nothrow 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; ++} ++ ++ ++/** ++ * Tests and sets the bit. ++ * Params: ++ * p = a non-NULL pointer to an array of uints. ++ * index = a bit number, starting with bit 0 of p[0], ++ * and progressing. It addresses bits like the expression: ++--- ++p[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1))) ++--- ++ * Returns: ++ * A non-zero value if the bit was set, and a zero ++ * if it was clear. ++ * ++ * Example: ++ * --- ++import std.intrinsic; ++ ++int main() ++{ ++ uint array[2]; ++ ++ array[0] = 2; ++ array[1] = 0x100; ++ ++ printf("btc(array, 35) = %d\n", btc(array, 35)); ++ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); ++ ++ printf("btc(array, 35) = %d\n", btc(array, 35)); ++ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); ++ ++ printf("bts(array, 35) = %d\n", bts(array, 35)); ++ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); ++ ++ printf("btr(array, 35) = %d\n", btr(array, 35)); ++ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); ++ ++ printf("bt(array, 1) = %d\n", bt(array, 1)); ++ printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]); ++ ++ return 0; ++} ++ * --- ++ * Output: ++
++btc(array, 35) = 0
++array = [0]:x2, [1]:x108
++btc(array, 35) = -1
++array = [0]:x2, [1]:x100
++bts(array, 35) = 0
++array = [0]:x2, [1]:x108
++btr(array, 35) = -1
++array = [0]:x2, [1]:x100
++bt(array, 1) = -1
++array = [0]:x2, [1]:x100
++
++ */ ++nothrow 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; ++} ++ ++/** ++ * Swaps bytes in a 4 byte uint end-to-end, i.e. byte 0 becomes ++ * byte 3, byte 1 becomes byte 2, byte 2 becomes byte 1, byte 3 ++ * becomes byte 0. ++ */ ++pragma(intrinsic, "llvm.bswap.i32") ++ uint bswap(uint val); ++ ++/** ++ * Reads I/O port at port_address. ++ */ ++ubyte inp(uint p) { throw new Exception("inp intrinsic not yet implemented"); } ++ ++/** ++ * ditto ++ */ ++ushort inpw(uint p) { throw new Exception("inpw intrinsic not yet implemented"); } ++ ++/** ++ * ditto ++ */ ++uint inpl(uint p) { throw new Exception("inpl intrinsic not yet implemented"); } ++ ++/** ++ * ditto ++ */ ++ubyte outp(uint p, ubyte v) { throw new Exception("outp intrinsic not yet implemented"); } ++ ++/** ++ * ditto ++ */ ++ushort outpw(uint p, ushort v) { throw new Exception("outpw intrinsic not yet implemented"); } ++ ++/** ++ * ditto ++ */ ++uint outpl(uint p, uint v) { throw new Exception("outpl intrinsic not yet implemented"); } diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 65d6523a..f0567092 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -214,15 +214,8 @@ void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr) Logger::println("SetArray"); LLValue *arr = array->getLVal(); assert(isaStruct(arr->getType()->getContainedType(0))); -#if 1 DtoStore(dim, DtoGEPi(arr,0,0)); DtoStore(ptr, DtoGEPi(arr,0,1)); -#else - DSliceValue *slice = DtoResizeDynArray(array->type, array, dim); - DtoMemCpy(DtoArrayPtr(array), ptr, dim); - DtoStore(dim, DtoGEPi(arr,0,0)); - DtoStore(slice->ptr, DtoGEPi(arr,0,1)); -#endif } ////////////////////////////////////////////////////////////////////////////////////////// @@ -424,6 +417,24 @@ static bool isInitialized(Type* et) { return true; } +////////////////////////////////////////////////////////////////////////////////////////// + +static DSliceValue *getSlice(Type *arrayType, LLValue *array) +{ + // Get ptr and length of the array + LLValue* newArrayLVal = DtoRawAlloca(array->getType(), 0, "newArray"); + DtoStore(array, newArrayLVal); + LLValue* arrayLen = DtoLoad(DtoGEPi(newArrayLVal,0,0)); + LLValue* newptr = DtoLoad(DtoGEPi(newArrayLVal,0,1)); + + // cast pointer to wanted type + const LLType* dstType = DtoType(arrayType)->getContainedType(1); + if (newptr->getType() != dstType) + newptr = DtoBitCast(newptr, dstType, ".gc_mem"); + + return new DSliceValue(arrayType, arrayLen, newptr); +} + ////////////////////////////////////////////////////////////////////////////////////////// DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool defaultInit) { @@ -442,11 +453,24 @@ DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool default if (defaultInit && !isInitialized(eltType)) defaultInit = false; bool zeroInit = eltType->isZeroInit(); + +#if DMDV2 + + const char* fnname = zeroInit ? "_d_newarrayT" : "_d_newarrayiT"; + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname); + + // call allocator + LLValue* newArray = gIR->CreateCallOrInvoke2(fn, arrayTypeInfo, arrayLen, ".gc_mem").getInstruction(); + + return getSlice(arrayType, newArray); + +#else + const char* fnname = defaultInit ? (zeroInit ? "_d_newarrayT" : "_d_newarrayiT") : "_d_newarrayvT"; LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, fnname); // call allocator - LLValue* newptr = gIR->CreateCallOrInvoke2(fn, arrayTypeInfo, arrayLen, ".gc_mem").getInstruction(); + LLValue* array = gIR->CreateCallOrInvoke2(fn, arrayTypeInfo, arrayLen, ".gc_mem").getInstruction(); // cast to wanted type const LLType* dstType = DtoType(arrayType)->getContainedType(1); @@ -457,6 +481,9 @@ DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool default Logger::cout() << "final ptr = " << *newptr << '\n'; return new DSliceValue(arrayType, arrayLen, newptr); + + +#endif } ////////////////////////////////////////////////////////////////////////////////////////// @@ -525,18 +552,29 @@ DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, LLValue* newdim) LLSmallVector args; args.push_back(DtoTypeInfoOf(arrayType)); args.push_back(newdim); - args.push_back(DtoArrayLen(array)); + +#if DMDV2 + + args.push_back(DtoBitCast(array->getLVal(), fn->getFunctionType()->getParamType(2))); + LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".gc_mem").getInstruction(); + + return getSlice(arrayType, newArray); + +#else LLValue* arrPtr = DtoArrayPtr(array); + args.push_back(DtoArrayLen(array)); + if (Logger::enabled()) Logger::cout() << "arrPtr = " << *arrPtr << '\n'; args.push_back(DtoBitCast(arrPtr, fn->getFunctionType()->getParamType(3), "tmp")); - LLValue* newptr = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".gc_mem").getInstruction(); if (newptr->getType() != arrPtr->getType()) newptr = DtoBitCast(newptr, arrPtr->getType(), ".gc_mem"); return new DSliceValue(arrayType, newdim, newptr); + +#endif } ////////////////////////////////////////////////////////////////////////////////////////// @@ -559,6 +597,36 @@ void DtoCatAssignElement(Loc& loc, Type* arrayType, DValue* array, Expression* e } ////////////////////////////////////////////////////////////////////////////////////////// + +#if DMDV2 + +DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp) +{ + Logger::println("DtoCatAssignArray"); + LOG_SCOPE; + Type *arrayType = arr->getType(); + DValue* valueToAppend = exp->toElem(gIR); + + // Prepare arguments + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arrayappendT"); + LLSmallVector args; + // TypeInfo ti + args.push_back(DtoTypeInfoOf(arrayType)); + // byte[] *px + args.push_back(DtoBitCast(arr->getLVal(), fn->getFunctionType()->getParamType(1))); + // byte[] y + LLValue *y = makeLValue(exp->loc, valueToAppend); + y = DtoBitCast(y, getPtrToType(fn->getFunctionType()->getParamType(2))); + args.push_back(DtoLoad(y)); + + // Call _d_arrayappendT + LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction(); + + return getSlice(arrayType, newArray); +} + +#else + DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp) { Logger::println("DtoCatAssignArray"); @@ -589,7 +657,39 @@ DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp) return slice; } +#endif + ////////////////////////////////////////////////////////////////////////////////////////// + +#if DMDV2 + +DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2) +{ + Logger::println("DtoCatAssignArray"); + LOG_SCOPE; + + // Prepare arguments + LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arraycatT"); + LLSmallVector args; + // TypeInfo ti + args.push_back(DtoTypeInfoOf(arrayType)); + // byte[] x + LLValue *val = makeLValue(exp1->loc, exp1->toElem(gIR)); + val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(1))); + args.push_back(DtoLoad(val)); + // byte[] y + val = makeLValue(exp2->loc, exp2->toElem(gIR)); + val = DtoBitCast(val, getPtrToType(fn->getFunctionType()->getParamType(2))); + args.push_back(DtoLoad(val)); + + // Call _d_arraycatT + LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction(); + + return getSlice(arrayType, newArray); +} + +#else + DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2) { Logger::println("DtoCatArrays"); @@ -630,6 +730,8 @@ DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2) return slice; } +#endif + ////////////////////////////////////////////////////////////////////////////////////////// DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2) { diff --git a/gen/runtime.cpp b/gen/runtime.cpp index b4d01581..da00abbe 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -175,7 +175,9 @@ static void LLVM_D_BuildRuntimeModule() Logger::println("building aggr types"); const LLType* voidPtrTy = rt_ptr(byteTy); - const LLType* stringTy = rt_array(byteTy); + const LLType* voidArrayTy = rt_array(byteTy); + const LLType* voidArrayPtrTy = getPtrToType(voidArrayTy); + const LLType* stringTy = voidArrayTy; const LLType* wstringTy = rt_array(shortTy); const LLType* dstringTy = rt_array(intTy); @@ -271,7 +273,7 @@ static void LLVM_D_BuildRuntimeModule() llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) ->setAttributes(Attr_NoAlias); } - +#if DMDV1 // void* _d_newarrayT(TypeInfo ti, size_t length) // void* _d_newarrayiT(TypeInfo ti, size_t length) // void* _d_newarrayvT(TypeInfo ti, size_t length) @@ -290,6 +292,20 @@ static void LLVM_D_BuildRuntimeModule() llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname3, M) ->setAttributes(Attr_NoAlias); } +#else + // void[] _d_newarrayT(TypeInfo ti, size_t length) + // void[] _d_newarrayiT(TypeInfo ti, size_t length) + { + llvm::StringRef fname("_d_newarrayT"); + llvm::StringRef fname2("_d_newarrayiT"); + std::vector types; + types.push_back(typeInfoTy); + types.push_back(sizeTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); + } +#endif // void* _d_newarraymT(TypeInfo ti, size_t length, size_t* dims) // void* _d_newarraymiT(TypeInfo ti, size_t length, size_t* dims) @@ -311,32 +327,71 @@ static void LLVM_D_BuildRuntimeModule() ->setAttributes(Attr_NoAlias_3_NoCapture); } + // D1: // void* _d_arraysetlengthT(TypeInfo ti, size_t newlength, size_t plength, void* pdata) // void* _d_arraysetlengthiT(TypeInfo ti, size_t newlength, size_t plength, void* pdata) + // D2: + // void[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, void[] *array) + // void[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, void[] *array) { llvm::StringRef fname("_d_arraysetlengthT"); llvm::StringRef fname2("_d_arraysetlengthiT"); std::vector types; types.push_back(typeInfoTy); types.push_back(sizeTy); +#if DMDV2 + types.push_back(voidArrayPtrTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); +#else types.push_back(sizeTy); types.push_back(voidPtrTy); const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false); +#endif llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); } - - // void* _d_arrayappendcT(TypeInfo ti, void* array, void* element) + // D1: + // byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) + // D2: + // byte[] _d_arrayappendcT(TypeInfo ti, byte[]* array, byte* element) { llvm::StringRef fname("_d_arrayappendcT"); std::vector types; types.push_back(typeInfoTy); +#if DMDV2 + types.push_back(voidArrayPtrTy); +#else types.push_back(voidPtrTy); +#endif types.push_back(voidPtrTy); - const llvm::FunctionType* fty = llvm::FunctionType::get(rt_array(byteTy), types, false); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } +#if DMDV2 + // void[] _d_arrayappendT(TypeInfo ti, byte[]* px, byte[] y) + { + llvm::StringRef fname("_d_arrayappendT"); + std::vector types; + types.push_back(typeInfoTy); + types.push_back(voidArrayPtrTy); + types.push_back(voidArrayTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + + // byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) + { + llvm::StringRef fname("_d_arraycatT"); + std::vector types; + types.push_back(typeInfoTy); + types.push_back(voidArrayTy); + types.push_back(voidArrayTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } +#endif + // Object _d_allocclass(ClassInfo ci) { llvm::StringRef fname(_d_allocclass);