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-orig/import/ldc/cstdarg.di druntime/import/ldc/cstdarg.di
--- druntime-orig/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-orig/import/ldc/intrinsics.di druntime/import/ldc/intrinsics.di
--- druntime-orig/import/ldc/intrinsics.di 1970-01-01 03:00:00.000000000 +0300
+++ druntime/import/ldc/intrinsics.di 2010-10-30 19:17:52.538555000 +0400
@@ -0,0 +1,359 @@
+/*
+ * 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.
+
+version(LDC_LLVMPre28)
+{
+ pragma(intrinsic, "llvm.memcpy.i#")
+ void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment);
+}
+else
+{
+ pragma(intrinsic, "llvm.memcpy.p0i8.p0i8.i#")
+ void llvm_memcpy(T)(void* dst, void* src, T len, uint alignment, bool volatile_ = false);
+}
+
+
+// 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.
+
+
+version(LDC_LLVMPre28)
+{
+ pragma(intrinsic, "llvm.memmove.i#")
+ void llvm_memmove(T)(void* dst, void* src, T len, uint alignment);
+}
+else
+{
+ pragma(intrinsic, "llvm.memmove.p0i8.p0i8.i#")
+ void llvm_memmove(T)(void* dst, void* src, T len, uint alignment, bool volatile_ = false);
+}
+
+
+// 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.
+
+version(LDC_LLVMPre28)
+{
+ pragma(intrinsic, "llvm.memset.i#")
+ void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment);
+}
+else
+{
+ pragma(intrinsic, "llvm.memset.p0i8.i#")
+ void llvm_memset(T)(void* dst, ubyte val, T len, uint alignment, bool volatile_ = false);
+}
+
+
+// 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.
+
+@safe nothrow pure pragma(intrinsic, "llvm.sqrt.f#")
+ T llvm_sqrt(T)(T val);
+
+
+// The 'llvm.sin.*' intrinsics return the sine of the operand.
+
+@safe nothrow pure pragma(intrinsic, "llvm.sin.f#")
+ T llvm_sin(T)(T val);
+
+
+// The 'llvm.cos.*' intrinsics return the cosine of the operand.
+
+@safe nothrow pure pragma(intrinsic, "llvm.cos.f#")
+ T llvm_cos(T)(T val);
+
+
+// The 'llvm.powi.*' intrinsics return the first operand raised to the specified
+// (positive or negative) power. The order of evaluation of multiplications is
+// not defined. When a vector of floating point type is used, the second
+// argument remains a scalar integer value.
+
+pragma(intrinsic, "llvm.powi.f#")
+ T llvm_powi(T)(T val, int power);
+
+
+// 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);
+
+
+//
+// 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);
+
+
+// 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);
+
+
+// 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);
+
+
+// The 'llvm.cttz' family of intrinsic functions counts the number of trailing
+// zeros.
+
+pragma(intrinsic, "llvm.cttz.i#")
+ T llvm_cttz(T)(T src);
+
+
+// The 'llvm.part.select' family of intrinsic functions selects a range of bits
+// from an integer value and returns them in the same bit width as the original
+// value.
+
+pragma(intrinsic, "llvm.part.select.i#")
+ T llvm_part_select(T)(T val, uint loBit, uint hiBit);
+
+
+// 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-orig/import/ldc/llvmasm.di druntime/import/ldc/llvmasm.di
--- druntime-orig/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-orig/import/ldc/vararg.d druntime/import/ldc/vararg.d
--- druntime-orig/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-orig/import/object.di druntime/import/object.di
--- druntime-orig/import/object.di 2010-09-03 12:28:52.000000000 +0400
+++ druntime/import/object.di 2010-10-27 00:22:27.444925001 +0400
@@ -130,7 +130,7 @@
Interface[] interfaces;
TypeInfo_Class base;
void* destructor;
- void(*classInvariant)(Object);
+ void function(Object) classInvariant;
uint m_flags;
// 1: // is IUnknown or is derived from IUnknown
// 2: // has no possible pointers into GC memory
@@ -140,7 +140,7 @@
// 32: // has typeinfo member
void* deallocator;
OffsetTypeInfo[] m_offTi;
- void* defaultConstructor;
+ void function(Object) defaultConstructor; // default Constructor
const(MemberInfo[]) function(string) xgetMembers;
static TypeInfo_Class find(in char[] classname);
@@ -179,7 +179,7 @@
class TypeInfo_Const : TypeInfo
{
- TypeInfo next;
+ TypeInfo base;
}
class TypeInfo_Invariant : TypeInfo_Const
@@ -288,7 +288,6 @@
interface TraceInfo
{
int opApply(scope int delegate(ref char[]));
- string toString();
}
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' -- druntime-orig/src/core/atomic.d druntime/src/core/atomic.d
--- druntime-orig/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;
}
}
+
+////////////////////////////////////////////////////////////////////////////////
+// LDC Atomics Implementation
+////////////////////////////////////////////////////////////////////////////////
+
+else version( LDC )
+{
+ import ldc.intrinsics;
+
+ T atomicOp(string op, T, V1)( ref shared T val, V1 mod )
+ if( is( NakedType!(V1) == NakedType!(T) ) )
+ {
+ // binary operators
+ //
+ // + - * / % ^^ &
+ // | ^ << >> >>> ~ in
+ // == != < <= > >=
+ static if( op == "+" || op == "-" || op == "*" || op == "/" ||
+ op == "%" || op == "^^" || op == "&" || op == "|" ||
+ op == "^" || op == "<<" || op == ">>" || op == ">>>" ||
+ op == "~" || // skip "in"
+ op == "==" || op == "!=" || op == "<" || op == "<=" ||
+ op == ">" || op == ">=" )
+ {
+ T get = val; // compiler can do atomic load
+ mixin( "return get " ~ op ~ " mod;" );
+ }
+ else
+ // assignment operators
+ //
+ // += -= *= /= %= ^^= &=
+ // |= ^= <<= >>= >>>= ~=
+ static if( op == "+=" || op == "-=" || op == "*=" || op == "/=" ||
+ op == "%=" || op == "^^=" || op == "&=" || op == "|=" ||
+ op == "^=" || op == "<<=" || op == ">>=" || op == ">>>=" ) // skip "~="
+ {
+ T get, set;
+
+ do
+ {
+ get = set = atomicLoad!(msync.raw)( val );
+ mixin( "set " ~ op ~ " mod;" );
+ } while( !cas( &val, get, set ) );
+ return set;
+ }
+ else
+ {
+ static assert( false, "Operation not supported." );
+ }
+ }
+
+ bool cas(T,V1,V2)( shared(T)* here, const V1 ifThis, const V2 writeThis )
+ if( is( NakedType!(V1) == NakedType!(T) ) &&
+ is( NakedType!(V2) == NakedType!(T) ) )
+
+ {
+ T oldval = void;
+ static if (is(T P == U*, U))
+ {
+ oldval = cast(T)llvm_atomic_cmp_swap!(size_t)(cast(shared size_t*)&writeThis, cast(size_t)ifThis, cast(size_t)here);
+ }
+ else static if (is(T == bool))
+ {
+ oldval = llvm_atomic_cmp_swap!(ubyte)(cast(shared ubyte*)&writeThis, ifThis?1:0, here?1:0)?0:1;
+ }
+ else
+ {
+ oldval = llvm_atomic_cmp_swap!(T)(here, ifThis, writeThis);
+ }
+ return oldval == ifThis;
+ }
+
+
+ private
+ {
+ enum msync
+ {
+ raw, /// not sequenced
+ acq, /// hoist-load + hoist-store barrier
+ rel, /// sink-load + sink-store barrier
+ seq, /// fully sequenced (acq + rel)
+ }
+
+ T atomicLoad(msync ms = msync.seq, T)( const ref shared T val )
+ {
+ llvm_memory_barrier(
+ ms == msync.acq || ms == msync.seq,
+ ms == msync.acq || ms == msync.seq,
+ ms == msync.rel || ms == msync.seq,
+ ms == msync.rel || ms == msync.seq,
+ false);
+ static if (is(T P == U*, U)) // pointer
+ {
+ return cast(T)llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 0);
+ }
+ else static if (is(T == bool))
+ {
+ return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0;
+ }
+ else
+ {
+ return llvm_atomic_load_add!(T)(&val, cast(T)0);
+ }
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// x86_32 Atomic Function Implementation
+////////////////////////////////////////////////////////////////////////////////
+
else version( AsmX86_32 )
{
T atomicOp(string op, T, V1)( ref shared T val, V1 mod )
@@ -396,6 +507,12 @@
}
}
}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// x86_64 Atomic Function Implementation
+////////////////////////////////////////////////////////////////////////////////
+
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' -- druntime-orig/src/core/stdc/math.d druntime/src/core/stdc/math.d
--- druntime-orig/src/core/stdc/math.d 2010-09-03 12:28:52.000000000 +0400
+++ druntime/src/core/stdc/math.d 2010-10-26 16:47:04.036925000 +0400
@@ -17,6 +17,7 @@
extern (C):
nothrow:
+pure: // LDC
alias float float_t;
alias double double_t;
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-orig/src/core/stdc/stdlib.d druntime/src/core/stdc/stdlib.d
--- druntime-orig/src/core/stdc/stdlib.d 2010-08-05 05:39:08.000000000 +0400
+++ druntime/src/core/stdc/stdlib.d 2010-10-26 19:26:03.996925001 +0400
@@ -92,3 +92,13 @@
{
void* alloca(size_t size); // non-standard
}
+else version( LDC )
+{
+ pragma(alloca)
+ void* alloca(size_t size);
+}
+else version( GNU )
+{
+ private import gcc.builtins;
+ alias gcc.builtins.__builtin_alloca alloca;
+}
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-orig/src/gc/gcbits.d druntime/src/gc/gcbits.d
--- druntime-orig/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;
}
+else version (LDC)
+{
+ version = bitops;
+}
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' -- druntime-orig/src/gc/gcx.d druntime/src/gc/gcx.d
--- druntime-orig/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()
- { int dummy;
+ {
+ int dummy;
(cast(byte*)&this)[0 .. Gcx.sizeof] = 0;
stackBottom = cast(char*)&dummy;
@@ -2200,7 +2201,7 @@
if ((cast(size_t)p & ~(PAGESIZE-1)) == pcache)
continue;
- auto pool = findPool(p);
+ auto pool = findPool(p);
if (pool)
{
size_t offset = cast(size_t)(p - pool.baseAddr);
@@ -2270,80 +2271,129 @@
__builtin_unwind_init();
sp = & sp;
}
+ else version(LDC)
+ {
+ version(X86)
+ {
+ uint eax,ecx,edx,ebx,ebp,esi,edi;
+ asm
+ {
+ mov eax[EBP], EAX ;
+ mov ecx[EBP], ECX ;
+ mov edx[EBP], EDX ;
+ mov ebx[EBP], EBX ;
+ mov ebp[EBP], EBP ;
+ mov esi[EBP], ESI ;
+ mov edi[EBP], EDI ;
+ mov sp[EBP], ESP ;
+ }
+ }
+ else version (X86_64)
+ {
+ ulong rax,rbx,rcx,rdx,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15;
+ asm
+ {
+ movq rax[RBP], RAX ;
+ movq rbx[RBP], RBX ;
+ movq rcx[RBP], RCX ;
+ movq rdx[RBP], RDX ;
+ movq rbp[RBP], RBP ;
+ movq rsi[RBP], RSI ;
+ movq rdi[RBP], RDI ;
+ movq r8 [RBP], R8 ;
+ movq r9 [RBP], R9 ;
+ movq r10[RBP], R10 ;
+ movq r11[RBP], R11 ;
+ movq r12[RBP], R12 ;
+ movq r13[RBP], R13 ;
+ movq r14[RBP], R14 ;
+ movq r15[RBP], R15 ;
+ movq sp[RBP], RSP ;
+ }
+ }
+ else
+ {
+ static assert( false, "Architecture not supported." );
+ }
+ }
else version( D_InlineAsm_X86 )
{
- asm
- {
- pushad ;
- mov sp[EBP],ESP ;
- }
+ asm
+ {
+ pushad ;
+ mov sp[EBP],ESP ;
+ }
+ }
+ else version ( D_InlineAsm_X86_64 )
+ {
+ asm
+ {
+ push RAX ;
+ push RBX ;
+ push RCX ;
+ push RDX ;
+ push RSI ;
+ push RDI ;
+ push RBP ;
+ push R8 ;
+ push R9 ;
+ push R10 ;
+ push R11 ;
+ push R12 ;
+ push R13 ;
+ push R14 ;
+ push R15 ;
+ push EAX ; // 16 byte align the stack
+ }
+ }
+ else
+ {
+ static assert( false, "Architecture not supported." );
}
- else version ( D_InlineAsm_X86_64 )
- {
- asm
- {
- push RAX ;
- push RBX ;
- push RCX ;
- push RDX ;
- push RSI ;
- push RDI ;
- push RBP ;
- push R8 ;
- push R9 ;
- push R10 ;
- push R11 ;
- push R12 ;
- push R13 ;
- push R14 ;
- push R15 ;
- push EAX ; // 16 byte align the stack
- }
- }
- else
- {
- static assert( false, "Architecture not supported." );
- }
result = fullcollect(sp);
- version( GNU )
- {
- // registers will be popped automatically
- }
- else version( D_InlineAsm_X86 )
- {
- asm
- {
- popad;
- }
- }
- else version ( D_InlineAsm_X86_64 )
- {
- asm
- {
- pop EAX ; // 16 byte align the stack
- pop R15 ;
- pop R14 ;
- pop R13 ;
- pop R12 ;
- pop R11 ;
- pop R10 ;
- pop R9 ;
- pop R8 ;
- pop RBP ;
- pop RDI ;
- pop RSI ;
- pop RDX ;
- pop RCX ;
- pop RBX ;
- pop RAX ;
- }
- }
- else
- {
- static assert( false, "Architecture not supported." );
- }
+ version( GNU )
+ {
+ // registers will be popped automatically
+ }
+ else version(LDC)
+ {
+ // nothing to do
+ }
+ else version( D_InlineAsm_X86 )
+ {
+ asm
+ {
+ popad;
+ }
+ }
+ else version ( D_InlineAsm_X86_64 )
+ {
+ asm
+ {
+ pop EAX ; // 16 byte align the stack
+ pop R15 ;
+ pop R14 ;
+ pop R13 ;
+ pop R12 ;
+ pop R11 ;
+ pop R10 ;
+ pop R9 ;
+ pop R8 ;
+ pop RBP ;
+ pop RDI ;
+ pop RSI ;
+ pop RDX ;
+ pop RCX ;
+ pop RBX ;
+ pop RAX ;
+ }
+ }
+ else
+ {
+ static assert( false, "Architecture not supported." );
+ }
return result;
}
@@ -2357,7 +2407,7 @@
Pool* pool;
debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
- //printf("\tpool address range = %p .. %p\n", minAddr, maxAddr);
+ //printf("\tpool address range = %p .. %p\n", minAddr, maxAddr);
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' -- druntime-orig/src/object_.d druntime/src/object_.d
--- druntime-orig/src/object_.d 2010-09-03 12:28:52.000000000 +0400
+++ druntime/src/object_.d 2010-11-02 19:34:56.773360001 +0300
@@ -1040,7 +1040,13 @@
override size_t tsize() { return base.tsize(); }
override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
- override TypeInfo next() { return base.next(); }
+ override TypeInfo next()
+ {
+ version(LDC)
+ return base;
+ else
+ return base.next();
+ }
override uint flags() { return base.flags(); }
override void[] init() { return base.init(); }
@@ -1663,7 +1669,6 @@
{
int len = 0;
ModuleReference *mr;
-
for (mr = _Dmodule_ref; mr; mr = mr.next)
len++;
_moduleinfo_array = new ModuleInfo*[len];
@@ -2025,7 +2030,6 @@
_d_monitor_create(h);
m = getMonitor(h);
}
-
IMonitor i = m.impl;
if (i is null)
@@ -2124,7 +2128,7 @@
size_t _aaLen(void* p);
void* _aaGet(void** pp, TypeInfo keyti, size_t valuesize, ...);
void* _aaGetRvalue(void* p, TypeInfo keyti, size_t valuesize, ...);
- void* _aaIn(void* p, TypeInfo keyti);
+ void* _aaIn(void* p, TypeInfo keyti, ...);
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);
@@ -2169,7 +2173,7 @@
return *cast(Key[]*) &a;
}
- int opApply(scope int delegate(ref Key, ref Value) dg)
+ int opApply(scope int delegate(ref Key, ref const Value) dg)
{
return _aaApply2(p, aligntsize(Key.sizeof), cast(_dg2_t)dg);
}
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-orig/src/rt/aaA.d druntime/src/rt/aaA.d
--- druntime-orig/src/rt/aaA.d 2010-08-05 05:39:06.000000000 +0400
+++ druntime/src/rt/aaA.d 2010-10-29 10:48:36.165035001 +0400
@@ -204,7 +204,7 @@
* Add entry for key if it is not already there.
*/
-void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
+void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, void *pkey)
in
{
assert(aa);
@@ -218,7 +218,6 @@
}
body
{
- auto pkey = cast(void *)(&valuesize + 1);
size_t i;
aaA *e;
//printf("keyti = %p\n", keyti);
@@ -274,13 +273,12 @@
* Returns null if it is not already there.
*/
-void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
+void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void *pkey)
{
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
if (!aa.a)
return null;
- auto pkey = cast(void *)(&valuesize + 1);
auto keysize = aligntsize(keyti.tsize());
auto len = aa.a.b.length;
@@ -312,7 +310,7 @@
* !=null in aa, return pointer to value
*/
-void* _aaIn(AA aa, TypeInfo keyti, ...)
+void* _aaIn(AA aa, TypeInfo keyti, void *pkey)
in
{
}
@@ -324,8 +322,6 @@
{
if (aa.a)
{
- auto pkey = cast(void *)(&keyti + 1);
-
//printf("_aaIn(), .length = %d, .ptr = %x\n", aa.a.length, cast(uint)aa.a.ptr);
auto len = aa.a.b.length;
@@ -357,9 +353,8 @@
* If key is not in aa[], do nothing.
*/
-void _aaDel(AA aa, TypeInfo keyti, ...)
+void _aaDel(AA aa, TypeInfo keyti, void *pkey)
{
- auto pkey = cast(void *)(&keyti + 1);
aaA *e;
if (aa.a && aa.a.b.length)
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-orig/src/rt/adi.d druntime/src/rt/adi.d
--- druntime-orig/src/rt/adi.d 2010-08-05 05:39:06.000000000 +0400
+++ druntime/src/rt/adi.d 2010-10-29 11:49:52.065035002 +0400
@@ -35,6 +35,8 @@
extern (C) void gc_free( void* p );
}
+version (DMD) version (X86)
+ version = DMD_X86;
struct Array
{
@@ -48,7 +50,7 @@
* reversed.
*/
-extern (C) long _adReverseChar(char[] a)
+extern (C) char[] _adReverseChar(char[] a)
{
if (a.length > 1)
{
@@ -108,7 +110,7 @@
hi = hi - 1 + (stridehi - stridelo);
}
}
- return *cast(long*)(&a);
+ return a;
}
unittest
@@ -143,7 +145,7 @@
* reversed.
*/
-extern (C) long _adReverseWchar(wchar[] a)
+extern (C) wchar[] _adReverseWchar(wchar[] a)
{
if (a.length > 1)
{
@@ -201,7 +203,7 @@
hi = hi - 1 + (stridehi - stridelo);
}
}
- return *cast(long*)(&a);
+ return a;
}
unittest
@@ -225,10 +227,10 @@
* Support for array.reverse property.
*/
-extern (C) long _adReverse(Array a, size_t szelem)
+extern (C) void[] _adReverse(void[] a, size_t szelem)
out (result)
{
- assert(result is *cast(long*)(&a));
+ assert(result.ptr is a.ptr);
}
body
{
@@ -267,7 +269,7 @@
//gc_free(tmp);
}
}
- return *cast(long*)(&a);
+ return a;
}
unittest
@@ -311,7 +313,7 @@
* Sort array of chars.
*/
-extern (C) long _adSortChar(char[] a)
+extern (C) char[] _adSortChar(char[] a)
{
if (a.length > 1)
{
@@ -326,14 +328,14 @@
}
delete da;
}
- return *cast(long*)(&a);
+ return a;
}
/**********************************************
* Sort array of wchars.
*/
-extern (C) long _adSortWchar(wchar[] a)
+extern (C) wchar[] _adSortWchar(wchar[] a)
{
if (a.length > 1)
{
@@ -348,7 +350,7 @@
}
delete da;
}
- return *cast(long*)(&a);
+ return a;
}
/***************************************
@@ -358,7 +360,7 @@
* 0 not equal
*/
-extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
+extern (C) int _adEq(void[] a1, void[] a2, TypeInfo ti)
{
debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
if (a1.length != a2.length)
@@ -379,7 +381,7 @@
return 1; // equal
}
-extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti)
+extern (C) int _adEq2(void[] a1, void[] a2, TypeInfo ti)
{
debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
if (a1.length != a2.length)
@@ -405,7 +407,7 @@
* Support for array compare test.
*/
-extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
+extern (C) int _adCmp(void[] a1, void[] a2, TypeInfo ti)
{
debug(adi) printf("adCmp()\n");
auto len = a1.length;
@@ -435,7 +437,7 @@
return (a1.length > a2.length) ? 1 : -1;
}
-extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti)
+extern (C) int _adCmp2(void[] a1, void[] a2, TypeInfo ti)
{
debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
return ti.compare(&a1, &a2);
@@ -461,9 +463,9 @@
* Support for array compare test.
*/
-extern (C) int _adCmpChar(Array a1, Array a2)
+extern (C) int _adCmpChar(void[] a1, void[] a2)
{
- version (X86)
+ version (DMD_X86)
{
asm
{ naked ;
@@ -569,8 +571,8 @@
ret ;
}
- }
- else
+ }
+ else
{
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' -- druntime-orig/src/rt/alloca.d druntime/src/rt/alloca.d
--- druntime-orig/src/rt/alloca.d 2010-08-05 05:39:06.000000000 +0400
+++ druntime/src/rt/alloca.d 2010-10-08 22:31:50.989547000 +0400
@@ -12,6 +12,9 @@
*/
module rt.alloca;
+version (DMD)
+{
+
/+
#if DOS386
extern size_t _x386_break;
@@ -133,3 +136,5 @@
ret ;
}
}
+
+}
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-orig/src/rt/arrayInit.d druntime/src/rt/arrayInit.d
--- druntime-orig/src/rt/arrayInit.d 1970-01-01 03:00:00.000000000 +0300
+++ druntime/src/rt/arrayInit.d 2010-11-02 14:39:21.353360001 +0300
@@ -0,0 +1,150 @@
+private import ldc.intrinsics;
+
+extern(C):
+
+int memcmp(void*,void*,size_t);
+size_t strlen(char*);
+
+// 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)
+{
+ if (dstlen != 0) assert(dst);
+ if (dstlen != 0) 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!size_t(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-orig/src/rt/ldc_eh.d druntime/src/rt/ldc_eh.d
--- druntime-orig/src/rt/ldc_eh.d 1970-01-01 03:00:00.000000000 +0300
+++ druntime/src/rt/ldc_eh.d 2010-10-29 10:43:18.469035000 +0400
@@ -0,0 +1,428 @@
+/**
+ * This module contains functions and structures required for
+ * exception handling.
+ */
+module ldc_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-orig/src/rt/lifetime.d druntime/src/rt/lifetime.d
--- druntime-orig/src/rt/lifetime.d 2010-08-05 05:39:06.000000000 +0400
+++ druntime/src/rt/lifetime.d 2010-11-02 14:51:10.000000000 +0300
@@ -92,6 +92,18 @@
return gc_malloc(sz);
}
+version (LDC)
+{
+
+/**
+ * for allocating a single POD value
+ */
+extern (C) void* _d_allocmemoryT(TypeInfo ti)
+{
+ return gc_malloc(ti.tsize(), !(ti.flags() & 1) ? BlkAttr.NO_SCAN : 0);
+}
+
+} // version (LDC)
/**
*
@@ -670,7 +682,7 @@
* ti is the type of the resulting array, or pointer to element.
* (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 +714,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 +723,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 +776,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 +785,7 @@
/**
*
*/
-extern (C) ulong _d_newarraymT(TypeInfo ti, int ndims, ...)
+extern (C) void[] _d_newarraymT(TypeInfo ti, int ndims, ...)
{
ulong result;
@@ -823,14 +835,14 @@
}
va_end(q);
}
- return result;
+ return *cast(void[]*)&result;
}
/**
*
*/
-extern (C) ulong _d_newarraymiT(TypeInfo ti, int ndims, ...)
+extern (C) void[] _d_newarraymiT(TypeInfo ti, int ndims, ...)
{
ulong result;
@@ -881,7 +893,7 @@
}
va_end(q);
}
- return result;
+ return *cast(void[]*)&result;
}
@@ -1381,7 +1393,7 @@
* 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,7 +1480,7 @@
L1:
px.length = newlength;
memcpy(px.data + length * sizeelem, y.ptr, y.length * sizeelem);
- return *cast(long*)px;
+ return *cast(void[]*)px;
}
@@ -1552,21 +1564,36 @@
return newcap;
}
+version (LDC)
+{
+
+/**
+ * Appends a single element to an array.
+ */
+extern (C) void[] _d_arrayappendcT(TypeInfo ti, byte[] *x, byte *argp)
+{
+ return _d_arrayappendT(ti, cast(Array*)x, argp[0..1]);
+}
+
+}
+else
+{
/**
*
*/
-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 +1639,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;
@@ -1798,7 +1825,7 @@
/**
*
*/
-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 +1846,7 @@
r.length = a.length;
memcpy(r.ptr, a.ptr, size);
}
- return *cast(long*)(&r);
+ return *cast(void[]*)(&r);
}
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-orig/src/rt/qsort.d druntime/src/rt/qsort.d
--- druntime-orig/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. */
-extern (C) long _adSort(Array a, TypeInfo ti)
+extern (C) void[] _adSort(void[] a, TypeInfo ti)
{
byte* base;
byte*[40] stack; // stack
@@ -124,7 +124,7 @@
limit = sp[1];
}
else // else stack empty, all done
- return *cast(long*)(&a);
+ return a;
}
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' -- druntime-orig/src/rt/qsort2.d druntime/src/rt/qsort2.d
--- druntime-orig/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);
}
-extern (C) long _adSort(Array a, TypeInfo ti)
+extern (C) void[] _adSort(void[] a, TypeInfo ti)
{
synchronized
{
tiglobal = ti;
qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
}
- return *cast(long*)(&a);
+ return a;
}
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-orig/src/rt/trace.d druntime/src/rt/trace.d
--- druntime-orig/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
- { naked ;
+ {
pushad ;
sub ESP,12 ;
}
@@ -870,7 +870,7 @@
else
{
asm
- { naked ;
+ {
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' -- druntime-orig/src/std/intrinsic.d druntime/src/std/intrinsic.d
--- druntime-orig/src/std/intrinsic.d 1970-01-01 03:00:00.000000000 +0300
+++ druntime/src/std/intrinsic.d 2010-10-26 20:18:29.668925001 +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.
+ */
+pure 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
+ */
+pure 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.
+ */
+pure nothrow int bt(const 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. + */ +pure nothrow 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"); }