mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-23 16:23:14 +01:00
Added copy of druntime from DMD 2.020 modified for LDC.
This commit is contained in:
7
druntime/src/build-dmd.bat
Normal file
7
druntime/src/build-dmd.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
@echo off
|
||||
set OLDHOME=%HOME%
|
||||
set HOME=%CD%
|
||||
make clean -fdmd-win32.mak
|
||||
make lib install -fdmd-win32.mak
|
||||
make clean -fdmd-win32.mak
|
||||
set HOME=%OLDHOME%
|
||||
19
druntime/src/build-dmd.sh
Normal file
19
druntime/src/build-dmd.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OLDHOME=$HOME
|
||||
export HOME=`pwd`
|
||||
|
||||
goerror(){
|
||||
export HOME=$OLDHOME
|
||||
echo "="
|
||||
echo "= *** Error ***"
|
||||
echo "="
|
||||
exit 1
|
||||
}
|
||||
|
||||
make clean -fdmd-posix.mak || goerror
|
||||
make lib doc install -fdmd-posix.mak || goerror
|
||||
make clean -fdmd-posix.mak || goerror
|
||||
chmod 644 ../import/*.di || goerror
|
||||
|
||||
export HOME=$OLDHOME
|
||||
19
druntime/src/build-ldc.sh
Normal file
19
druntime/src/build-ldc.sh
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
OLDHOME=$HOME
|
||||
export HOME=`pwd`
|
||||
|
||||
goerror(){
|
||||
export HOME=$OLDHOME
|
||||
echo "="
|
||||
echo "= *** Error ***"
|
||||
echo "="
|
||||
exit 1
|
||||
}
|
||||
|
||||
make clean -fldc-gcc.mak || goerror
|
||||
make lib doc install -fldc-gcc.mak || goerror
|
||||
make clean -fldc-gcc.mak || goerror
|
||||
chmod 644 ../import/*.di || goerror
|
||||
|
||||
export HOME=$OLDHOME
|
||||
290
druntime/src/common/core/bitmanip.d
Normal file
290
druntime/src/common/core/bitmanip.d
Normal file
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
* This module contains a collection of bit-level operations.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Walter Bright, Don Clugston, Sean Kelly
|
||||
*/
|
||||
module core.bitmanip;
|
||||
|
||||
|
||||
version( DDoc )
|
||||
{
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
int bsf( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* 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 core.bitmanip;
|
||||
*
|
||||
* 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<br>
|
||||
* bsr(x21) = 5
|
||||
*/
|
||||
int bsr( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* Tests the bit.
|
||||
*/
|
||||
int bt( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Tests and complements the bit.
|
||||
*/
|
||||
int btc( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* Tests and resets (sets to 0) the bit.
|
||||
*/
|
||||
int btr( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* 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 core.bitmanip;
|
||||
|
||||
int main()
|
||||
{
|
||||
uint array[2];
|
||||
|
||||
array[0] = 2;
|
||||
array[1] = 0x100;
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btc(array, 35) = %d\n", <b>btc</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bts(array, 35) = %d\n", <b>bts</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("btr(array, 35) = %d\n", <b>btr</b>(array, 35));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
printf("bt(array, 1) = %d\n", <b>bt</b>(array, 1));
|
||||
printf("array = [0]:x%x, [1]:x%x\n", array[0], array[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
* ---
|
||||
* Output:
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
*/
|
||||
int bts( uint* p, uint bitnum );
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
uint bswap( uint v );
|
||||
|
||||
|
||||
/**
|
||||
* Reads I/O port at port_address.
|
||||
*/
|
||||
ubyte inp( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
ushort inpw( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
uint inpl( uint port_address );
|
||||
|
||||
|
||||
/**
|
||||
* Writes and returns value to I/O port at port_address.
|
||||
*/
|
||||
ubyte outp( uint port_address, ubyte value );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
ushort outpw( uint port_address, ushort value );
|
||||
|
||||
|
||||
/**
|
||||
* ditto
|
||||
*/
|
||||
uint outpl( uint port_address, uint value );
|
||||
}
|
||||
else version( LDC )
|
||||
{
|
||||
public import ldc.bitmanip;
|
||||
}
|
||||
else
|
||||
{
|
||||
public import std.intrinsic;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the number of set bits in a 32-bit integer.
|
||||
*/
|
||||
int popcnt( uint x )
|
||||
{
|
||||
// Avoid branches, and the potential for cache misses which
|
||||
// could be incurred with a table lookup.
|
||||
|
||||
// We need to mask alternate bits to prevent the
|
||||
// sum from overflowing.
|
||||
// add neighbouring bits. Each bit is 0 or 1.
|
||||
x = x - ((x>>1) & 0x5555_5555);
|
||||
// now each two bits of x is a number 00,01 or 10.
|
||||
// now add neighbouring pairs
|
||||
x = ((x&0xCCCC_CCCC)>>2) + (x&0x3333_3333);
|
||||
// now each nibble holds 0000-0100. Adding them won't
|
||||
// overflow any more, so we don't need to mask any more
|
||||
|
||||
// Now add the nibbles, then the bytes, then the words
|
||||
// We still need to mask to prevent double-counting.
|
||||
// Note that if we used a rotate instead of a shift, we
|
||||
// wouldn't need the masks, and could just divide the sum
|
||||
// by 8 to account for the double-counting.
|
||||
// On some CPUs, it may be faster to perform a multiply.
|
||||
|
||||
x += (x>>4);
|
||||
x &= 0x0F0F_0F0F;
|
||||
x += (x>>8);
|
||||
x &= 0x00FF_00FF;
|
||||
x += (x>>16);
|
||||
x &= 0xFFFF;
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
debug( UnitTest )
|
||||
{
|
||||
unittest
|
||||
{
|
||||
assert( popcnt( 0 ) == 0 );
|
||||
assert( popcnt( 7 ) == 3 );
|
||||
assert( popcnt( 0xAA )== 4 );
|
||||
assert( popcnt( 0x8421_1248 ) == 8 );
|
||||
assert( popcnt( 0xFFFF_FFFF ) == 32 );
|
||||
assert( popcnt( 0xCCCC_CCCC ) == 16 );
|
||||
assert( popcnt( 0x7777_7777 ) == 24 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverses the order of bits in a 32-bit integer.
|
||||
*/
|
||||
uint bitswap( uint x )
|
||||
{
|
||||
|
||||
version( D_InlineAsm_X86 )
|
||||
{
|
||||
asm
|
||||
{
|
||||
// Author: Tiago Gasiba.
|
||||
mov EDX, EAX;
|
||||
shr EAX, 1;
|
||||
and EDX, 0x5555_5555;
|
||||
and EAX, 0x5555_5555;
|
||||
shl EDX, 1;
|
||||
or EAX, EDX;
|
||||
mov EDX, EAX;
|
||||
shr EAX, 2;
|
||||
and EDX, 0x3333_3333;
|
||||
and EAX, 0x3333_3333;
|
||||
shl EDX, 2;
|
||||
or EAX, EDX;
|
||||
mov EDX, EAX;
|
||||
shr EAX, 4;
|
||||
and EDX, 0x0f0f_0f0f;
|
||||
and EAX, 0x0f0f_0f0f;
|
||||
shl EDX, 4;
|
||||
or EAX, EDX;
|
||||
bswap EAX;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// swap odd and even bits
|
||||
x = ((x >> 1) & 0x5555_5555) | ((x & 0x5555_5555) << 1);
|
||||
// swap consecutive pairs
|
||||
x = ((x >> 2) & 0x3333_3333) | ((x & 0x3333_3333) << 2);
|
||||
// swap nibbles
|
||||
x = ((x >> 4) & 0x0F0F_0F0F) | ((x & 0x0F0F_0F0F) << 4);
|
||||
// swap bytes
|
||||
x = ((x >> 8) & 0x00FF_00FF) | ((x & 0x00FF_00FF) << 8);
|
||||
// swap 2-byte long pairs
|
||||
x = ( x >> 16 ) | ( x << 16);
|
||||
return x;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
debug( UnitTest )
|
||||
{
|
||||
unittest
|
||||
{
|
||||
assert( bitswap( 0x8000_0100 ) == 0x0080_0001 );
|
||||
}
|
||||
}
|
||||
276
druntime/src/common/core/exception.d
Normal file
276
druntime/src/common/core/exception.d
Normal file
@@ -0,0 +1,276 @@
|
||||
/**
|
||||
* The exception module defines all system-level exceptions and provides a
|
||||
* mechanism to alter system-level error handling.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.exception;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
alias void function( string file, size_t line, string msg = null ) assertHandlerType;
|
||||
|
||||
assertHandlerType assertHandler = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an array bounds error.
|
||||
*/
|
||||
class ArrayBoundsException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Array index out of bounds", file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an assert error.
|
||||
*/
|
||||
class AssertException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Assertion failure", file, line );
|
||||
}
|
||||
|
||||
this( string msg, string file, size_t line )
|
||||
{
|
||||
super( msg, file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on finalize error.
|
||||
*/
|
||||
class FinalizeException : Exception
|
||||
{
|
||||
ClassInfo info;
|
||||
|
||||
this( ClassInfo c, Exception e = null )
|
||||
{
|
||||
super( "Finalization error", e );
|
||||
info = c;
|
||||
}
|
||||
|
||||
override string toString()
|
||||
{
|
||||
return "An exception was thrown while finalizing an instance of class " ~ info.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on hidden function error.
|
||||
*/
|
||||
class HiddenFuncException : Exception
|
||||
{
|
||||
this( ClassInfo ci )
|
||||
{
|
||||
super( "Hidden method called for " ~ ci.name );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on an out of memory error.
|
||||
*/
|
||||
class OutOfMemoryException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "Memory allocation failed", file, line );
|
||||
}
|
||||
|
||||
override string toString()
|
||||
{
|
||||
return msg ? super.toString() : "Memory allocation failed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on a switch error.
|
||||
*/
|
||||
class SwitchException : Exception
|
||||
{
|
||||
this( string file, size_t line )
|
||||
{
|
||||
super( "No appropriate switch clause found", file, line );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thrown on a unicode conversion error.
|
||||
*/
|
||||
class UnicodeException : Exception
|
||||
{
|
||||
size_t idx;
|
||||
|
||||
this( string msg, size_t idx )
|
||||
{
|
||||
super( msg );
|
||||
this.idx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overrides
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default assert hander with a user-supplied version.
|
||||
*
|
||||
* Params:
|
||||
* h = The new assert handler. Set to null to use the default handler.
|
||||
*/
|
||||
void setAssertHandler( assertHandlerType h )
|
||||
{
|
||||
assertHandler = h;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overridable Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A callback for assert errors in D. The user-supplied assert handler will
|
||||
* be called if one has been supplied, otherwise an AssertException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*/
|
||||
extern (C) void onAssertError( string file, size_t line )
|
||||
{
|
||||
if( assertHandler is null )
|
||||
throw new AssertException( file, line );
|
||||
assertHandler( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for assert errors in D. The user-supplied assert handler will
|
||||
* be called if one has been supplied, otherwise an AssertException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
* msg = An error message supplied by the user.
|
||||
*/
|
||||
extern (C) void onAssertErrorMsg( string file, size_t line, string msg )
|
||||
{
|
||||
if( assertHandler is null )
|
||||
throw new AssertException( msg, file, line );
|
||||
assertHandler( file, line, msg );
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Internal Error Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* A callback for array bounds errors in D. An ArrayBoundsException will be
|
||||
* thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*
|
||||
* Throws:
|
||||
* ArrayBoundsException.
|
||||
*/
|
||||
extern (C) void onArrayBoundsError( string file, size_t line )
|
||||
{
|
||||
throw new ArrayBoundsException( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for finalize errors in D. A FinalizeException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* e = The exception thrown during finalization.
|
||||
*
|
||||
* Throws:
|
||||
* FinalizeException.
|
||||
*/
|
||||
extern (C) void onFinalizeError( ClassInfo info, Exception ex )
|
||||
{
|
||||
throw new FinalizeException( info, ex );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for hidden function errors in D. A HiddenFuncException will be
|
||||
* thrown.
|
||||
*
|
||||
* Throws:
|
||||
* HiddenFuncException.
|
||||
*/
|
||||
extern (C) void onHiddenFuncError( Object o )
|
||||
{
|
||||
throw new HiddenFuncException( o.classinfo );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for out of memory errors in D. An OutOfMemoryException will be
|
||||
* thrown.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException.
|
||||
*/
|
||||
extern (C) void onOutOfMemoryError()
|
||||
{
|
||||
// NOTE: Since an out of memory condition exists, no allocation must occur
|
||||
// while generating this object.
|
||||
throw cast(OutOfMemoryException) cast(void*) OutOfMemoryException.classinfo.init;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for switch errors in D. A SwitchException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* file = The name of the file that signaled this error.
|
||||
* line = The line number on which this error occurred.
|
||||
*
|
||||
* Throws:
|
||||
* SwitchException.
|
||||
*/
|
||||
extern (C) void onSwitchError( string file, size_t line )
|
||||
{
|
||||
throw new SwitchException( file, line );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A callback for unicode errors in D. A UnicodeException will be thrown.
|
||||
*
|
||||
* Params:
|
||||
* msg = Information about the error.
|
||||
* idx = String index where this error was detected.
|
||||
*
|
||||
* Throws:
|
||||
* UnicodeException.
|
||||
*/
|
||||
extern (C) void onUnicodeError( string msg, size_t idx )
|
||||
{
|
||||
throw new UnicodeException( msg, idx );
|
||||
}
|
||||
484
druntime/src/common/core/memory.d
Normal file
484
druntime/src/common/core/memory.d
Normal file
@@ -0,0 +1,484 @@
|
||||
/**
|
||||
* The memory module provides an interface to the garbage collector and to
|
||||
* any other OS or API-level memory management facilities.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.memory;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
extern (C) void gc_init();
|
||||
extern (C) void gc_term();
|
||||
|
||||
extern (C) void gc_enable();
|
||||
extern (C) void gc_disable();
|
||||
extern (C) void gc_collect();
|
||||
extern (C) void gc_minimize();
|
||||
|
||||
extern (C) uint gc_getAttr( void* p );
|
||||
extern (C) uint gc_setAttr( void* p, uint a );
|
||||
extern (C) uint gc_clrAttr( void* p, uint a );
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_realloc( void* p, size_t sz, uint ba = 0 );
|
||||
extern (C) size_t gc_extend( void* p, size_t mx, size_t sz );
|
||||
extern (C) size_t gc_reserve( size_t sz );
|
||||
extern (C) void gc_free( void* p );
|
||||
|
||||
extern (C) void* gc_addrOf( void* p );
|
||||
extern (C) size_t gc_sizeOf( void* p );
|
||||
|
||||
struct BlkInfo_
|
||||
{
|
||||
void* base;
|
||||
size_t size;
|
||||
uint attr;
|
||||
}
|
||||
|
||||
extern (C) BlkInfo_ gc_query( void* p );
|
||||
|
||||
extern (C) void gc_addRoot( void* p );
|
||||
extern (C) void gc_addRange( void* p, size_t sz );
|
||||
|
||||
extern (C) void gc_removeRoot( void* p );
|
||||
extern (C) void gc_removeRange( void* p );
|
||||
|
||||
extern (C) void* gc_getHandle();
|
||||
extern (C) void gc_setHandle( void* p );
|
||||
extern (C) void gc_endHandle();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This struct encapsulates all garbage collection functionality for the D
|
||||
* programming language.
|
||||
*/
|
||||
struct GC
|
||||
{
|
||||
/**
|
||||
* Enables the garbage collector if collections have previously been
|
||||
* suspended by a call to disable. This function is reentrant, and
|
||||
* must be called once for every call to disable before the garbage
|
||||
* collector is enabled.
|
||||
*/
|
||||
static void enable()
|
||||
{
|
||||
gc_enable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disables the garbage collector. This function is reentrant, but
|
||||
* enable must be called once for each call to disable.
|
||||
*/
|
||||
static void disable()
|
||||
{
|
||||
gc_disable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Begins a full collection. While the meaning of this may change based
|
||||
* on the garbage collector implementation, typical behavior is to scan
|
||||
* all stack segments for roots, mark accessible memory blocks as alive,
|
||||
* and then to reclaim free space. This action may need to suspend all
|
||||
* running threads for at least part of the collection process.
|
||||
*/
|
||||
static void collect()
|
||||
{
|
||||
gc_collect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the managed memory space be minimized by returning free
|
||||
* physical memory to the operating system. The amount of free memory
|
||||
* returned depends on the allocator design and on program behavior.
|
||||
*/
|
||||
static void minimize()
|
||||
{
|
||||
gc_minimize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Elements for a bit field representing memory block attributes. These
|
||||
* are manipulated via the getAttr, setAttr, clrAttr functions.
|
||||
*/
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001, /// Finalize the data in this block on collect.
|
||||
NO_SCAN = 0b0000_0010, /// Do not scan through this block on collect.
|
||||
NO_MOVE = 0b0000_0100 /// Do not move this memory block on collect.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contains aggregate information about a block of managed memory. The
|
||||
* purpose of this struct is to support a more efficient query style in
|
||||
* instances where detailed information is needed.
|
||||
*
|
||||
* base = A pointer to the base of the block in question.
|
||||
* size = The size of the block, calculated from base.
|
||||
* attr = Attribute bits set on the memory block.
|
||||
*/
|
||||
alias BlkInfo_ BlkInfo;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a bit field representing all block attributes set for the memory
|
||||
* referenced by p. If p references memory not originally allocated by
|
||||
* this garbage collector, points to the interior of a memory block, or if
|
||||
* p is null, zero will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*
|
||||
* Returns:
|
||||
* A bit field containing any bits set for the memory block referenced by
|
||||
* p or zero on error.
|
||||
*/
|
||||
static uint getAttr( void* p )
|
||||
{
|
||||
return gc_getAttr( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the specified bits for the memory references by p. If p references
|
||||
* memory not originally allocated by this garbage collector, points to the
|
||||
* interior of a memory block, or if p is null, no action will be
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* a = A bit field containing any bits to set for this memory block.
|
||||
*
|
||||
* The result of a call to getAttr after the specified bits have been
|
||||
* set.
|
||||
*/
|
||||
static uint setAttr( void* p, uint a )
|
||||
{
|
||||
return gc_setAttr( p, a );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the specified bits for the memory references by p. If p
|
||||
* references memory not originally allocated by this garbage collector,
|
||||
* points to the interior of a memory block, or if p is null, no action
|
||||
* will be performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* a = A bit field containing any bits to clear for this memory block.
|
||||
*
|
||||
* Returns:
|
||||
* The result of a call to getAttr after the specified bits have been
|
||||
* cleared.
|
||||
*/
|
||||
static uint clrAttr( void* p, uint a )
|
||||
{
|
||||
return gc_clrAttr( p, a );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests an aligned block of managed memory from the garbage collector.
|
||||
* This memory may be deleted at will with a call to free, or it may be
|
||||
* discarded and cleaned up automatically during a collection run. If
|
||||
* allocation fails, this function will call onOutOfMemory which is
|
||||
* expected to throw an OutOfMemoryException.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory or null if insufficient memory
|
||||
* is available.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* malloc( size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_malloc( sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests an aligned block of managed memory from the garbage collector,
|
||||
* which is initialized with all bits set to zero. This memory may be
|
||||
* deleted at will with a call to free, or it may be discarded and cleaned
|
||||
* up automatically during a collection run. If allocation fails, this
|
||||
* function will call onOutOfMemory which is expected to throw an
|
||||
* OutOfMemoryException.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory or null if insufficient memory
|
||||
* is available.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* calloc( size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_calloc( sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If sz is zero, the memory referenced by p will be deallocated as if
|
||||
* by a call to free. A new memory block of size sz will then be
|
||||
* allocated as if by a call to malloc, or the implementation may instead
|
||||
* resize the memory block in place. The contents of the new memory block
|
||||
* will be the same as the contents of the old memory block, up to the
|
||||
* lesser of the new and old sizes. Note that existing memory will only
|
||||
* be freed by realloc if sz is equal to zero. The garbage collector is
|
||||
* otherwise expected to later reclaim the memory block if it is unused.
|
||||
* If allocation fails, this function will call onOutOfMemory which is
|
||||
* expected to throw an OutOfMemoryException. If p references memory not
|
||||
* originally allocated by this garbage collector, or if it points to the
|
||||
* interior of a memory block, no action will be taken. If ba is zero
|
||||
* (the default) and p references the head of a valid, known memory block
|
||||
* then any bits set on the current block will be set on the new block if a
|
||||
* reallocation is required. If ba is not zero and p references the head
|
||||
* of a valid, known memory block then the bits in ba will replace those on
|
||||
* the current memory block and will also be set on the new block if a
|
||||
* reallocation is required.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
* sz = The desired allocation size in bytes.
|
||||
* ba = A bitmask of the attributes to set on this block.
|
||||
*
|
||||
* Returns:
|
||||
* A reference to the allocated memory on success or null if sz is
|
||||
* zero. On failure, the original value of p is returned.
|
||||
*
|
||||
* Throws:
|
||||
* OutOfMemoryException on allocation failure.
|
||||
*/
|
||||
static void* realloc( void* p, size_t sz, uint ba = 0 )
|
||||
{
|
||||
return gc_realloc( p, sz, ba );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests that the managed memory block referenced by p be extended in
|
||||
* place by at least mx bytes, with a desired extension of sz bytes. If an
|
||||
* extension of the required size is not possible, if p references memory
|
||||
* not originally allocated by this garbage collector, or if p points to
|
||||
* the interior of a memory block, no action will be taken.
|
||||
*
|
||||
* Params:
|
||||
* mx = The minimum extension size in bytes.
|
||||
* sz = The desired extension size in bytes.
|
||||
*
|
||||
* Returns:
|
||||
* The size in bytes of the extended memory block referenced by p or zero
|
||||
* if no extension occurred.
|
||||
*/
|
||||
static size_t extend( void* p, size_t mx, size_t sz )
|
||||
{
|
||||
return gc_extend( p, mx, sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Requests that at least sz bytes of memory be obtained from the operating
|
||||
* system and marked as free.
|
||||
*
|
||||
* Params:
|
||||
* sz = The desired size in bytes.
|
||||
*
|
||||
* Returns:
|
||||
* The actual number of bytes reserved or zero on error.
|
||||
*/
|
||||
static size_t reserve( size_t sz )
|
||||
{
|
||||
return gc_reserve( sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deallocates the memory referenced by p. If p is null, no action
|
||||
* occurs. If p references memory not originally allocated by this
|
||||
* garbage collector, or if it points to the interior of a memory block,
|
||||
* no action will be taken. The block will not be finalized regardless
|
||||
* of whether the FINALIZE attribute is set. If finalization is desired,
|
||||
* use delete instead.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*/
|
||||
static void free( void* p )
|
||||
{
|
||||
gc_free( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the base address of the memory block containing p. This value
|
||||
* is useful to determine whether p is an interior pointer, and the result
|
||||
* may be passed to routines such as sizeOf which may otherwise fail. If p
|
||||
* references memory not originally allocated by this garbage collector, if
|
||||
* p is null, or if the garbage collector does not support this operation,
|
||||
* null will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root or the interior of a valid memory block or to
|
||||
* null.
|
||||
*
|
||||
* Returns:
|
||||
* The base address of the memory block referenced by p or null on error.
|
||||
*/
|
||||
static void* addrOf( void* p )
|
||||
{
|
||||
return gc_addrOf( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the true size of the memory block referenced by p. This value
|
||||
* represents the maximum number of bytes for which a call to realloc may
|
||||
* resize the existing block in place. If p references memory not
|
||||
* originally allocated by this garbage collector, points to the interior
|
||||
* of a memory block, or if p is null, zero will be returned.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root of a valid memory block or to null.
|
||||
*
|
||||
* Returns:
|
||||
* The size in bytes of the memory block referenced by p or zero on error.
|
||||
*/
|
||||
static size_t sizeOf( void* p )
|
||||
{
|
||||
return gc_sizeOf( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns aggregate information about the memory block containing p. If p
|
||||
* references memory not originally allocated by this garbage collector, if
|
||||
* p is null, or if the garbage collector does not support this operation,
|
||||
* BlkInfo.init will be returned. Typically, support for this operation
|
||||
* is dependent on support for addrOf.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to the root or the interior of a valid memory block or to
|
||||
* null.
|
||||
*
|
||||
* Returns:
|
||||
* Information regarding the memory block referenced by p or BlkInfo.init
|
||||
* on error.
|
||||
*/
|
||||
static BlkInfo query( void* p )
|
||||
{
|
||||
return gc_query( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the memory address referenced by p to an internal list of roots to
|
||||
* be scanned during a collection. If p is null, no operation is
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void addRoot( void* p )
|
||||
{
|
||||
gc_addRoot( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds the memory block referenced by p and of size sz to an internal list
|
||||
* of ranges to be scanned during a collection. If p is null, no operation
|
||||
* is performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
* sz = The size in bytes of the block to add. If sz is zero then the
|
||||
* no operation will occur. If p is null then sz must be zero.
|
||||
*/
|
||||
static void addRange( void* p, size_t sz )
|
||||
{
|
||||
gc_addRange( p, sz );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the memory block referenced by p from an internal list of roots
|
||||
* to be scanned during a collection. If p is null or does not represent
|
||||
* a value previously passed to add(void*) then no operation is performed.
|
||||
*
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void removeRoot( void* p )
|
||||
{
|
||||
gc_removeRoot( p );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the memory block referenced by p from an internal list of ranges
|
||||
* to be scanned during a collection. If p is null or does not represent
|
||||
* a value previously passed to add(void*, size_t) then no operation is
|
||||
* performed.
|
||||
*
|
||||
* Params:
|
||||
* p = A pointer to a valid memory address or to null.
|
||||
*/
|
||||
static void removeRange( void* p )
|
||||
{
|
||||
gc_removeRange( p );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get handle to the collector.
|
||||
* The only thing that can be done with this handle is pass it to
|
||||
* setHandle(). getHandle/setHandle/endHandle work together so that
|
||||
* if there are multiple instances of the gc running, only one instance
|
||||
* can be set to run.
|
||||
* The most common case of this is under Windows where a D application
|
||||
* calls functions in a DLL that is implemented in D.
|
||||
*/
|
||||
|
||||
static void* getHandle()
|
||||
{
|
||||
return gc_getHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set handle to the collector.
|
||||
* The handle p is an opaque handle, acquired by a call to
|
||||
* getHandle().
|
||||
*/
|
||||
|
||||
static void setHandle(void* p)
|
||||
{
|
||||
gc_setHandle(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when done using the collector specified by the
|
||||
* call to setHandle().
|
||||
*/
|
||||
|
||||
static void endHandle()
|
||||
{
|
||||
gc_endHandle();
|
||||
}
|
||||
}
|
||||
171
druntime/src/common/core/runtime.d
Normal file
171
druntime/src/common/core/runtime.d
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* The runtime module exposes information specific to the D runtime code.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module core.runtime;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
extern (C) bool rt_isHalting();
|
||||
|
||||
alias bool function() ModuleUnitTester;
|
||||
alias bool function(Object) CollectHandler;
|
||||
alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
|
||||
|
||||
extern (C) void rt_setCollectHandler( CollectHandler h );
|
||||
extern (C) void rt_setTraceHandler( TraceHandler h );
|
||||
|
||||
alias void delegate( Exception ) ExceptionHandler;
|
||||
extern (C) bool rt_init( ExceptionHandler dg = null );
|
||||
extern (C) bool rt_term( ExceptionHandler dg = null );
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Runtime
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This struct encapsulates all functionality related to the underlying runtime
|
||||
* module for the calling context.
|
||||
*/
|
||||
struct Runtime
|
||||
{
|
||||
/**
|
||||
* Initializes the runtime. This call is to be used in instances where the
|
||||
* standard program initialization process is not executed. This is most
|
||||
* often in shared libraries or in libraries linked to a C program.
|
||||
*
|
||||
* Params:
|
||||
* dg = A delegate which will receive any exception thrown during the
|
||||
* initialization process or null if such exceptions should be
|
||||
* discarded.
|
||||
*
|
||||
* Returns:
|
||||
* true if initialization succeeds and false if initialization fails.
|
||||
*/
|
||||
static bool initialize( void delegate( Exception ) dg = null )
|
||||
{
|
||||
return rt_init( dg );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Terminates the runtime. This call is to be used in instances where the
|
||||
* standard program termination process will not be not executed. This is
|
||||
* most often in shared libraries or in libraries linked to a C program.
|
||||
*
|
||||
* Params:
|
||||
* dg = A delegate which will receive any exception thrown during the
|
||||
* termination process or null if such exceptions should be
|
||||
* discarded.
|
||||
*
|
||||
* Returns:
|
||||
* true if termination succeeds and false if termination fails.
|
||||
*/
|
||||
static bool terminate( void delegate( Exception ) dg = null )
|
||||
{
|
||||
return rt_term( dg );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the runtime is halting. Under normal circumstances,
|
||||
* this will be set between the time that normal application code has
|
||||
* exited and before module dtors are called.
|
||||
*
|
||||
* Returns:
|
||||
* true if the runtime is halting.
|
||||
*/
|
||||
static bool isHalting()
|
||||
{
|
||||
return rt_isHalting();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default trace mechanism with s user-supplied version. A
|
||||
* trace represents the context from which an exception was thrown, and the
|
||||
* trace handler will be called when this occurs. The pointer supplied to
|
||||
* this routine indicates the base address from which tracing should occur.
|
||||
* If the supplied pointer is null then the trace routine should determine
|
||||
* an appropriate calling context from which to begin the trace.
|
||||
*
|
||||
* Params:
|
||||
* h = The new trace handler. Set to null to use the default handler.
|
||||
*/
|
||||
static void traceHandler( TraceHandler h )
|
||||
{
|
||||
rt_setTraceHandler( h );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default collect hander with a user-supplied version. This
|
||||
* routine will be called for each resource object that is finalized in a
|
||||
* non-deterministic manner--typically during a garbage collection cycle.
|
||||
* If the supplied routine returns true then the object's dtor will called
|
||||
* as normal, but if the routine returns false than the dtor will not be
|
||||
* called. The default behavior is for all object dtors to be called.
|
||||
*
|
||||
* Params:
|
||||
* h = The new collect handler. Set to null to use the default handler.
|
||||
*/
|
||||
static void collectHandler( CollectHandler h )
|
||||
{
|
||||
rt_setCollectHandler( h );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the default module unit tester with a user-supplied version.
|
||||
* This routine will be called once on program initialization. The return
|
||||
* value of this routine indicates to the runtime whether the body of the
|
||||
* program will be executed.
|
||||
*
|
||||
* Params:
|
||||
* h = The new unit tester. Set to null to use the default unit tester.
|
||||
*/
|
||||
static void moduleUnitTester( ModuleUnitTester h )
|
||||
{
|
||||
sm_moduleUnitTester = h;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static ModuleUnitTester sm_moduleUnitTester = null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Overridable Callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* This routine is called by the runtime to run module unit tests on startup.
|
||||
* The user-supplied unit tester will be called if one has been supplied,
|
||||
* otherwise all unit tests will be run in sequence.
|
||||
*
|
||||
* Returns:
|
||||
* true if execution should continue after testing is complete and false if
|
||||
* not. Default behavior is to return true.
|
||||
*/
|
||||
extern (C) bool runModuleUnitTests()
|
||||
{
|
||||
if( Runtime.sm_moduleUnitTester is null )
|
||||
{
|
||||
foreach( m; ModuleInfo )
|
||||
{
|
||||
if( m.unitTest )
|
||||
m.unitTest();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return Runtime.sm_moduleUnitTester();
|
||||
}
|
||||
3322
druntime/src/common/core/thread.d
Normal file
3322
druntime/src/common/core/thread.d
Normal file
File diff suppressed because it is too large
Load Diff
139
druntime/src/common/ldc.mak
Normal file
139
druntime/src/common/ldc.mak
Normal file
@@ -0,0 +1,139 @@
|
||||
# Makefile to build the D runtime library core components for Posix
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-core.a
|
||||
LIB_MASK=libdruntime-core*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=ldc2
|
||||
|
||||
INC_DEST=../../import
|
||||
LIB_DEST=../../lib
|
||||
DOC_DEST=../../doc
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core/bitmanip.o \
|
||||
core/exception.o \
|
||||
core/memory_.o \
|
||||
core/runtime.o \
|
||||
core/thread.o
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc/errno.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core/bitmanip.html \
|
||||
core/exception.html \
|
||||
core/memory.html \
|
||||
core/runtime.html \
|
||||
core/thread.html
|
||||
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core/bitmanip.o : core/bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core/bitmanip.d -of$@
|
||||
|
||||
### memory
|
||||
|
||||
core/memory_.o : core/memory.d
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core/thread.o : core/thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core/thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
find . -name "$(LIB_MASK)" | xargs $(RM)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)
|
||||
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
|
||||
$(MD) $(DOC_DEST)
|
||||
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
|
||||
$(MD) $(LIB_DEST)
|
||||
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
139
druntime/src/common/posix.mak
Normal file
139
druntime/src/common/posix.mak
Normal file
@@ -0,0 +1,139 @@
|
||||
# Makefile to build the D runtime library core components for Posix
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-core.a
|
||||
LIB_MASK=libdruntime-core*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=dmd
|
||||
|
||||
INC_DEST=../../import
|
||||
LIB_DEST=../../lib
|
||||
DOC_DEST=../../doc
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core/bitmanip.o \
|
||||
core/exception.o \
|
||||
core/memory_.o \
|
||||
core/runtime.o \
|
||||
core/thread.o
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc/errno.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core/bitmanip.html \
|
||||
core/exception.html \
|
||||
core/memory.html \
|
||||
core/runtime.html \
|
||||
core/thread.html
|
||||
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core/bitmanip.o : core/bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core/bitmanip.d -of$@
|
||||
|
||||
### memory
|
||||
|
||||
core/memory_.o : core/memory.d
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core/thread.o : core/thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core/thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
find . -name "$(LIB_MASK)" | xargs $(RM)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)
|
||||
find . -name "*.di" -exec cp -f {} $(INC_DEST)/{} \;
|
||||
$(MD) $(DOC_DEST)
|
||||
find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \;
|
||||
$(MD) $(LIB_DEST)
|
||||
find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \;
|
||||
21
druntime/src/common/stdc/errno.c
Normal file
21
druntime/src/common/stdc/errno.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* This file contains wrapper functions for macro-defined C rouines.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
int getErrno()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
|
||||
int setErrno( int val )
|
||||
{
|
||||
errno = val;
|
||||
return val;
|
||||
}
|
||||
130
druntime/src/common/win32.mak
Normal file
130
druntime/src/common/win32.mak
Normal file
@@ -0,0 +1,130 @@
|
||||
# Makefile to build the D runtime library core components for Win32
|
||||
# Designed to work with DigitalMars make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the common library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=druntime-core.lib
|
||||
LIB_MASK=druntime-core*.lib
|
||||
|
||||
CP=xcopy /y
|
||||
RM=del /f
|
||||
MD=mkdir
|
||||
|
||||
ADD_CFLAGS=
|
||||
ADD_DFLAGS=
|
||||
|
||||
CFLAGS=-mn -6 -r $(ADD_CFLAGS)
|
||||
#CFLAGS=-g -mn -6 -r $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=dmc
|
||||
LC=lib
|
||||
DC=dmd
|
||||
|
||||
INC_DEST=..\..\import
|
||||
LIB_DEST=..\..\lib
|
||||
DOC_DEST=..\..\doc
|
||||
|
||||
.DEFAULT: .asm .c .cpp .d .html .obj
|
||||
|
||||
.asm.obj:
|
||||
$(CC) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.obj:
|
||||
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
|
||||
# $(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
core : lib
|
||||
lib : core.lib
|
||||
doc : core.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_CORE= \
|
||||
core\bitmanip.obj \
|
||||
core\exception.obj \
|
||||
core\memory.obj \
|
||||
core\runtime.obj \
|
||||
core\thread.obj
|
||||
|
||||
OBJ_STDC= \
|
||||
stdc\errno.obj
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_CORE) \
|
||||
$(OBJ_STDC)
|
||||
|
||||
######################################################
|
||||
|
||||
DOC_CORE= \
|
||||
core\bitmanip.html \
|
||||
core\exception.html \
|
||||
core\memory.html \
|
||||
core\runtime.html \
|
||||
core\thread.html
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
core.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) -c -n $@ $(ALL_OBJS)
|
||||
|
||||
core.doc : $(ALL_DOCS)
|
||||
@echo Documentation generated.
|
||||
|
||||
######################################################
|
||||
|
||||
### bitmanip
|
||||
|
||||
core\bitmanip.obj : core\bitmanip.d
|
||||
$(DC) -c $(DFLAGS) core\bitmanip.d -of$@
|
||||
|
||||
### thread
|
||||
|
||||
core\thread.obj : core\thread.d
|
||||
$(DC) -c $(DFLAGS) -d -Hf$*.di core\thread.d -of$@
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
$(RM) /s .\*.di
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(INC_DEST)\.
|
||||
$(CP) /s *.di $(INC_DEST)\.
|
||||
$(MD) $(DOC_DEST)
|
||||
$(CP) /s *.html $(DOC_DEST)\.
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)\.
|
||||
408
druntime/src/compiler/dmd/aApply.d
Normal file
408
druntime/src/compiler/dmd/aApply.d
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aApply;
|
||||
|
||||
/* This code handles decoding UTF strings for foreach loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
// dg is D, but _aApplycd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplycd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ d = decode(aa, i);
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
d = decode(aa, i);
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
i++;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// dg is D, but _aApplycd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
n = 1;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplydc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
|
||||
foreach (size_t i, dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
auto j = i;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
974
druntime/src/compiler/dmd/aApplyR.d
Normal file
974
druntime/src/compiler/dmd/aApplyR.d
Normal file
@@ -0,0 +1,974 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aApplyR;
|
||||
|
||||
/* This code handles decoding UTF strings for foreach_reverse loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************/
|
||||
/* 1 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0;)
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 2 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
|
||||
for (i = len; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); assert(k == 8); break;
|
||||
case 1: assert(d == '\U00100456'); assert(k == 4); break;
|
||||
case 2: assert(d == '\u1234'); assert(k == 1); break;
|
||||
case 3: assert(d == 'a'); assert(k == 0); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == '\U00100456'); break;
|
||||
case 2: assert(k == 1); assert(d == '\u1234'); break;
|
||||
case 3: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 8); assert(d == 'b'); break;
|
||||
case 1: assert(k == 4); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 4); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 2); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
886
druntime/src/compiler/dmd/aaA.d
Normal file
886
druntime/src/compiler/dmd/aaA.d
Normal file
@@ -0,0 +1,886 @@
|
||||
//_ aaA.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Implementation of associative arrays.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2008 by Digital Mars, http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.aaA;
|
||||
|
||||
private
|
||||
{
|
||||
import stdc.stdarg;
|
||||
import stdc.string;
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
// Auto-rehash and pre-allocate - Dave Fladebo
|
||||
|
||||
static size_t[] prime_list = [
|
||||
97UL, 389UL,
|
||||
1_543UL, 6_151UL,
|
||||
24_593UL, 98_317UL,
|
||||
393_241UL, 1_572_869UL,
|
||||
6_291_469UL, 25_165_843UL,
|
||||
100_663_319UL, 402_653_189UL,
|
||||
1_610_612_741UL, 4_294_967_291UL,
|
||||
// 8_589_934_513UL, 17_179_869_143UL
|
||||
];
|
||||
|
||||
/* This is the type of the return value for dynamic arrays.
|
||||
* It should be a type that is returned in registers.
|
||||
* Although DMD will return types of Array in registers,
|
||||
* gcc will not, so we instead use a 'long'.
|
||||
*/
|
||||
alias long ArrayRet_t;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
struct aaA
|
||||
{
|
||||
aaA *left;
|
||||
aaA *right;
|
||||
hash_t hash;
|
||||
/* key */
|
||||
/* value */
|
||||
}
|
||||
|
||||
struct BB
|
||||
{
|
||||
aaA*[] b;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
TypeInfo keyti; // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
|
||||
}
|
||||
|
||||
/* This is the type actually seen by the programmer, although
|
||||
* it is completely opaque.
|
||||
*/
|
||||
|
||||
struct AA
|
||||
{
|
||||
BB* a;
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Align to next pointer boundary, so that
|
||||
* GC won't be faced with misaligned pointers
|
||||
* in value.
|
||||
*/
|
||||
|
||||
size_t aligntsize(size_t tsize)
|
||||
{
|
||||
// Is pointer alignment on the x64 4 bytes or 8?
|
||||
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
/*************************************************
|
||||
* Invariant for aa.
|
||||
*/
|
||||
|
||||
/+
|
||||
void _aaInvAh(aaA*[] aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa.length; i++)
|
||||
{
|
||||
if (aa[i])
|
||||
_aaInvAh_x(aa[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private int _aaCmpAh_x(aaA *e1, aaA *e2)
|
||||
{ int c;
|
||||
|
||||
c = e1.hash - e2.hash;
|
||||
if (c == 0)
|
||||
{
|
||||
c = e1.key.length - e2.key.length;
|
||||
if (c == 0)
|
||||
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void _aaInvAh_x(aaA *e)
|
||||
{
|
||||
hash_t key_hash;
|
||||
aaA *e1;
|
||||
aaA *e2;
|
||||
|
||||
key_hash = getHash(e.key);
|
||||
assert(key_hash == e.hash);
|
||||
|
||||
while (1)
|
||||
{ int c;
|
||||
|
||||
e1 = e.left;
|
||||
if (e1)
|
||||
{
|
||||
_aaInvAh_x(e1); // ordinary recursion
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e1, e);
|
||||
assert(c < 0);
|
||||
e1 = e1.right;
|
||||
} while (e1 != null);
|
||||
}
|
||||
|
||||
e2 = e.right;
|
||||
if (e2)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e, e2);
|
||||
assert(c < 0);
|
||||
e2 = e2.left;
|
||||
} while (e2 != null);
|
||||
e = e.right; // tail recursion
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
*/
|
||||
|
||||
size_t _aaLen(AA aa)
|
||||
in
|
||||
{
|
||||
//printf("_aaLen()+\n");
|
||||
//_aaInv(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
void _aaLen_x(aaA* ex)
|
||||
{
|
||||
auto e = ex;
|
||||
len++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (e.right)
|
||||
_aaLen_x(e.right);
|
||||
e = e.left;
|
||||
if (!e)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaLen_x(e);
|
||||
}
|
||||
}
|
||||
assert(len == result);
|
||||
|
||||
//printf("_aaLen()-\n");
|
||||
}
|
||||
body
|
||||
{
|
||||
return aa.a ? aa.a.nodes : 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Add entry for key if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGet(AA* aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
in
|
||||
{
|
||||
assert(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(result);
|
||||
assert(aa.a);
|
||||
assert(aa.a.b.length);
|
||||
//assert(_aaInAh(*aa.a, key));
|
||||
}
|
||||
body
|
||||
{
|
||||
auto pkey = cast(void *)(&valuesize + 1);
|
||||
size_t i;
|
||||
aaA *e;
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
|
||||
if (!aa.a)
|
||||
aa.a = new BB();
|
||||
aa.a.keyti = keyti;
|
||||
|
||||
if (!aa.a.b.length)
|
||||
{
|
||||
alias aaA *pa;
|
||||
auto len = prime_list[0];
|
||||
|
||||
aa.a.b = new pa[len];
|
||||
}
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % aa.a.b.length;
|
||||
auto pe = &aa.a.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
goto Lret;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
size_t size = aaA.sizeof + keysize + valuesize;
|
||||
e = cast(aaA *) gc_calloc(size);
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
|
||||
auto nodes = ++aa.a.nodes;
|
||||
//printf("length = %d, nodes = %d\n", (*aa.a).length, nodes);
|
||||
if (nodes > aa.a.b.length * 4)
|
||||
{
|
||||
_aaRehash(aa,keyti);
|
||||
}
|
||||
|
||||
Lret:
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Returns null if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
|
||||
{
|
||||
//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;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.a.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
return null; // not found, caller will throw exception
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Determine if key is in aa.
|
||||
* Returns:
|
||||
* null not in aa
|
||||
* !=null in aa, return pointer to value
|
||||
*/
|
||||
|
||||
void* _aaIn(AA aa, TypeInfo keyti, ...)
|
||||
in
|
||||
{
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//assert(result == 0 || result == 1);
|
||||
}
|
||||
body
|
||||
{
|
||||
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;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.a.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Delete key entry in aa[].
|
||||
* If key is not in aa[], do nothing.
|
||||
*/
|
||||
|
||||
void _aaDel(AA aa, TypeInfo keyti, ...)
|
||||
{
|
||||
auto pkey = cast(void *)(&keyti + 1);
|
||||
aaA *e;
|
||||
|
||||
if (aa.a && aa.a.b.length)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % aa.a.b.length;
|
||||
auto pe = &aa.a.b[i];
|
||||
while ((e = *pe) !is null) // null means not found
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
{
|
||||
if (!e.left && !e.right)
|
||||
{
|
||||
*pe = null;
|
||||
}
|
||||
else if (e.left && !e.right)
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
}
|
||||
else if (!e.left && e.right)
|
||||
{
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
do
|
||||
pe = &(*pe).right;
|
||||
while (*pe);
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
|
||||
aa.a.nodes--;
|
||||
gc_free(e);
|
||||
break;
|
||||
}
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of values from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaValues(AA aa, size_t keysize, size_t valuesize)
|
||||
in
|
||||
{
|
||||
assert(keysize == aligntsize(keysize));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t resi;
|
||||
Array a;
|
||||
|
||||
void _aaValues_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(a.ptr + resi * valuesize,
|
||||
cast(byte*)e + aaA.sizeof + keysize,
|
||||
valuesize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaValues_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
a.length = _aaLen(aa);
|
||||
a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
|
||||
valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaValues_x(e);
|
||||
}
|
||||
assert(resi == a.length);
|
||||
}
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Rehash an array.
|
||||
*/
|
||||
|
||||
void* _aaRehash(AA* paa, TypeInfo keyti)
|
||||
in
|
||||
{
|
||||
//_aaInvAh(paa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//_aaInvAh(result);
|
||||
}
|
||||
body
|
||||
{
|
||||
BB newb;
|
||||
|
||||
void _aaRehash_x(aaA* olde)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
auto left = olde.left;
|
||||
auto right = olde.right;
|
||||
olde.left = null;
|
||||
olde.right = null;
|
||||
|
||||
aaA *e;
|
||||
|
||||
//printf("rehash %p\n", olde);
|
||||
auto key_hash = olde.hash;
|
||||
size_t i = key_hash % newb.b.length;
|
||||
auto pe = &newb.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
|
||||
assert(e.left != e);
|
||||
assert(e.right != e);
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(olde + 1, e + 1);
|
||||
assert(c != 0);
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
*pe = olde;
|
||||
|
||||
if (right)
|
||||
{
|
||||
if (!left)
|
||||
{ olde = right;
|
||||
continue;
|
||||
}
|
||||
_aaRehash_x(right);
|
||||
}
|
||||
if (!left)
|
||||
break;
|
||||
olde = left;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Rehash\n");
|
||||
if (paa.a)
|
||||
{
|
||||
auto aa = paa.a;
|
||||
auto len = _aaLen(*paa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaRehash_x(e);
|
||||
}
|
||||
|
||||
newb.nodes = aa.nodes;
|
||||
newb.keyti = aa.keyti;
|
||||
}
|
||||
|
||||
*paa.a = newb;
|
||||
_aaBalance(paa);
|
||||
}
|
||||
return (*paa).a;
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* Balance an array.
|
||||
*/
|
||||
|
||||
void _aaBalance(AA* paa)
|
||||
{
|
||||
//printf("_aaBalance()\n");
|
||||
if (paa.a)
|
||||
{
|
||||
aaA*[16] tmp;
|
||||
aaA*[] array = tmp;
|
||||
auto aa = paa.a;
|
||||
foreach (j, e; aa.b)
|
||||
{
|
||||
/* Temporarily store contents of bucket in array[]
|
||||
*/
|
||||
size_t k = 0;
|
||||
void addToArray(aaA* e)
|
||||
{
|
||||
while (e)
|
||||
{ addToArray(e.left);
|
||||
if (k == array.length)
|
||||
array.length = array.length * 2;
|
||||
array[k++] = e;
|
||||
e = e.right;
|
||||
}
|
||||
}
|
||||
addToArray(e);
|
||||
/* The contents of the bucket are now sorted into array[].
|
||||
* Rebuild the tree.
|
||||
*/
|
||||
void buildTree(aaA** p, size_t x1, size_t x2)
|
||||
{
|
||||
if (x1 >= x2)
|
||||
*p = null;
|
||||
else
|
||||
{ auto mid = (x1 + x2) >> 1;
|
||||
*p = array[mid];
|
||||
buildTree(&(*p).left, x1, mid);
|
||||
buildTree(&(*p).right, mid + 1, x2);
|
||||
}
|
||||
}
|
||||
auto p = &aa.b[j];
|
||||
buildTree(p, 0, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
/********************************************
|
||||
* Produce array of N byte keys from aa.
|
||||
*/
|
||||
|
||||
ArrayRet_t _aaKeys(AA aa, size_t keysize)
|
||||
{
|
||||
byte[] res;
|
||||
size_t resi;
|
||||
|
||||
void _aaKeys_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaKeys_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
auto len = _aaLen(aa);
|
||||
if (!len)
|
||||
return 0;
|
||||
res = (cast(byte*) gc_malloc(len * keysize,
|
||||
!(aa.a.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0))[0 .. len * keysize];
|
||||
resi = 0;
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
_aaKeys_x(e);
|
||||
}
|
||||
assert(resi == len);
|
||||
|
||||
Array a;
|
||||
a.length = len;
|
||||
a.ptr = res.ptr;
|
||||
return *cast(ArrayRet_t*)(&a);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* 'apply' for associative arrays - to support foreach
|
||||
*/
|
||||
|
||||
// dg is D, but _aaApply() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
int _aaApply(AA aa, size_t keysize, dg_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// dg is D, but _aaApply2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa.a)
|
||||
{
|
||||
foreach (e; aa.a.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct an associative array of type ti from
|
||||
* length pairs of key/value pairs.
|
||||
*/
|
||||
|
||||
extern (C)
|
||||
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
|
||||
{
|
||||
auto valuesize = ti.next.tsize(); // value size
|
||||
auto keyti = ti.key;
|
||||
auto keysize = keyti.tsize(); // key size
|
||||
BB* result;
|
||||
|
||||
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
|
||||
//printf("tivalue = %.*s\n", ti.next.classinfo.name);
|
||||
if (length == 0 || valuesize == 0 || keysize == 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list q;
|
||||
va_start!(size_t)(q, length);
|
||||
|
||||
result = new BB();
|
||||
result.keyti = keyti;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (length <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
auto len = prime_list[i];
|
||||
result.b = new aaA*[len];
|
||||
|
||||
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
|
||||
size_t keytsize = aligntsize(keysize);
|
||||
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{ void* pkey = q;
|
||||
q += keystacksize;
|
||||
void* pvalue = q;
|
||||
q += valuestacksize;
|
||||
aaA* e;
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % len;
|
||||
auto pe = &result.b[i];
|
||||
while (1)
|
||||
{
|
||||
e = *pe;
|
||||
if (!e)
|
||||
{
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
result.nodes++;
|
||||
break;
|
||||
}
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
|
||||
}
|
||||
|
||||
va_end(q);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
625
druntime/src/compiler/dmd/adi.d
Normal file
625
druntime/src/compiler/dmd/adi.d
Normal file
@@ -0,0 +1,625 @@
|
||||
//_ adi.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Dynamic array property support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.adi;
|
||||
|
||||
//debug=adi; // uncomment to turn on debugging printf's
|
||||
|
||||
private
|
||||
{
|
||||
debug(adi) import stdc.stdio;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
import util.utf;
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of chars.
|
||||
* Handled separately because embedded multibyte encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
char[6] tmp;
|
||||
char[6] tmplo;
|
||||
char* lo = a.ptr;
|
||||
char* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
|
||||
if (clo <= 0x7F && chi <= 0x7F)
|
||||
{
|
||||
debug(adi) printf("\tascii\n");
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint stridelo = UTF8stride[clo];
|
||||
|
||||
uint stridehi = 1;
|
||||
while ((chi & 0xC0) == 0x80)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
|
||||
if (stridelo == stridehi)
|
||||
{
|
||||
|
||||
memcpy(tmp.ptr, lo, stridelo);
|
||||
memcpy(lo, hi, stridelo);
|
||||
memcpy(hi, tmp.ptr, stridelo);
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi);
|
||||
memcpy(tmplo.ptr, lo, stridelo);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - lo) - stridelo);
|
||||
memcpy(lo, tmp.ptr, stridehi);
|
||||
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
auto a = "abcd"c;
|
||||
|
||||
auto r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\u1235\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234\u1235a");
|
||||
|
||||
a = "ab\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234ba");
|
||||
|
||||
a = "\u3026\u2021\u3061\n";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "\n\u3061\u2021\u3026");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of wchars.
|
||||
* Handled separately because embedded multiword encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
wchar[2] tmp;
|
||||
wchar* lo = a.ptr;
|
||||
wchar* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
if ((clo < 0xD800 || clo > 0xDFFF) &&
|
||||
(chi < 0xD800 || chi > 0xDFFF))
|
||||
{
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
|
||||
|
||||
int stridehi = 1;
|
||||
if (chi >= 0xDC00 && chi <= 0xDFFF)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
if (stridelo == stridehi)
|
||||
{ int stmp;
|
||||
|
||||
assert(stridelo == 2);
|
||||
assert(stmp.sizeof == 2 * (*lo).sizeof);
|
||||
stmp = *cast(int*)lo;
|
||||
*cast(int*)lo = *cast(int*)hi;
|
||||
*cast(int*)hi = stmp;
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
|
||||
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
|
||||
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wstring a = "abcd";
|
||||
|
||||
auto r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\U00012356\U00012346c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012346\U00012356a");
|
||||
|
||||
a = "ab\U00012345c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012345ba");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property.
|
||||
*/
|
||||
|
||||
extern (C) long _adReverse(Array a, size_t szelem)
|
||||
out (result)
|
||||
{
|
||||
assert(result is *cast(long*)(&a));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
byte* tmp;
|
||||
byte[16] buffer;
|
||||
|
||||
void* lo = a.ptr;
|
||||
void* hi = a.ptr + (a.length - 1) * szelem;
|
||||
|
||||
tmp = buffer.ptr;
|
||||
if (szelem > 16)
|
||||
{
|
||||
//version (Windows)
|
||||
tmp = cast(byte*) alloca(szelem);
|
||||
//else
|
||||
//tmp = gc_malloc(szelem);
|
||||
}
|
||||
|
||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||
{
|
||||
memcpy(tmp, lo, szelem);
|
||||
memcpy(lo, hi, szelem);
|
||||
memcpy(hi, tmp, szelem);
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (szelem > 16)
|
||||
// BUG: bad code is generate for delete pointer, tries
|
||||
// to call delclass.
|
||||
//gc_free(tmp);
|
||||
}
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse.unittest\n");
|
||||
|
||||
int[] a = new int[5];
|
||||
int[] b;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
a[i] = i;
|
||||
b = a.reverse;
|
||||
assert(b is a);
|
||||
for (i = 0; i < 5; i++)
|
||||
assert(a[i] == 4 - i);
|
||||
|
||||
struct X20
|
||||
{ // More than 16 bytes in size
|
||||
int a;
|
||||
int b, c, d, e;
|
||||
}
|
||||
|
||||
X20[] c = new X20[5];
|
||||
X20[] d;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{ c[i].a = i;
|
||||
c[i].e = 10;
|
||||
}
|
||||
d = c.reverse;
|
||||
assert(d is c);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(c[i].a == 4 - i);
|
||||
assert(c[i].e == 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ char[4] buf;
|
||||
auto t = toUTF8(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) long _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ wchar[2] buf;
|
||||
auto t = toUTF16(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test.
|
||||
* Returns:
|
||||
* 1 equal
|
||||
* 0 not equal
|
||||
*/
|
||||
|
||||
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
auto sz = ti.tsize();
|
||||
auto p1 = a1.ptr;
|
||||
auto p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
// We should really have a ti.isPOD() check for this
|
||||
return (memcmp(p1, p2, a1.length) == 0);
|
||||
|
||||
for (size_t i = 0; i < a1.length; i++)
|
||||
{
|
||||
if (!ti.equals(p1 + i * sz, p2 + i * sz))
|
||||
return 0; // not equal
|
||||
}
|
||||
return 1; // equal
|
||||
}
|
||||
|
||||
extern (C) int _adEq2(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adEq2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
if (a1.length != a2.length)
|
||||
return 0; // not equal
|
||||
if (!ti.equals(&a1, &a2))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
assert(a != "betty");
|
||||
assert(a == "hello");
|
||||
assert(a != "hxxxx");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("adCmp()\n");
|
||||
auto len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
auto sz = ti.tsize();
|
||||
void *p1 = a1.ptr;
|
||||
void *p2 = a2.ptr;
|
||||
|
||||
if (sz == 1)
|
||||
{ // We should really have a ti.isPOD() check for this
|
||||
auto c = memcmp(p1, p2, len);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
auto c = ti.compare(p1 + i * sz, p2 + i * sz);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if (a1.length == a2.length)
|
||||
return 0;
|
||||
return (a1.length > a2.length) ? 1 : -1;
|
||||
}
|
||||
|
||||
extern (C) int _adCmp2(Array a1, Array a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("_adCmp2(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
|
||||
return ti.compare(&a1, &a2);
|
||||
}
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
*/
|
||||
|
||||
extern (C) int _adCmpChar(Array a1, Array a2)
|
||||
{
|
||||
version (X86)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
|
||||
mov ESI,a1+4[4+ESP] ;
|
||||
mov EDI,a2+4[4+ESP] ;
|
||||
|
||||
mov ECX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
cmp ECX,EDX ;
|
||||
jb GotLength ;
|
||||
|
||||
mov ECX,EDX ;
|
||||
|
||||
GotLength:
|
||||
cmp ECX,4 ;
|
||||
jb DoBytes ;
|
||||
|
||||
// Do alignment if neither is dword aligned
|
||||
test ESI,3 ;
|
||||
jz Aligned ;
|
||||
|
||||
test EDI,3 ;
|
||||
jz Aligned ;
|
||||
DoAlign:
|
||||
mov AL,[ESI] ; //align ESI to dword bounds
|
||||
mov DL,[EDI] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
inc ESI ;
|
||||
inc EDI ;
|
||||
|
||||
test ESI,3 ;
|
||||
|
||||
lea ECX,[ECX-1] ;
|
||||
jnz DoAlign ;
|
||||
Aligned:
|
||||
mov EAX,ECX ;
|
||||
|
||||
// do multiple of 4 bytes at a time
|
||||
|
||||
shr ECX,2 ;
|
||||
jz TryOdd ;
|
||||
|
||||
repe ;
|
||||
cmpsd ;
|
||||
|
||||
jnz UnequalQuad ;
|
||||
|
||||
TryOdd:
|
||||
mov ECX,EAX ;
|
||||
DoBytes:
|
||||
// if still equal and not end of string, do up to 3 bytes slightly
|
||||
// slower.
|
||||
|
||||
and ECX,3 ;
|
||||
jz Equal ;
|
||||
|
||||
repe ;
|
||||
cmpsb ;
|
||||
|
||||
jnz Unequal ;
|
||||
Equal:
|
||||
mov EAX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
sub EAX,EDX ;
|
||||
pop ESI ;
|
||||
|
||||
pop EDI ;
|
||||
ret ;
|
||||
|
||||
UnequalQuad:
|
||||
mov EDX,[EDI-4] ;
|
||||
mov EAX,[ESI-4] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
jnz Unequal ;
|
||||
|
||||
shr EAX,16 ;
|
||||
|
||||
shr EDX,16 ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
Unequal:
|
||||
sbb EAX,EAX ;
|
||||
pop ESI ;
|
||||
|
||||
or EAX,1 ;
|
||||
pop EDI ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
int c;
|
||||
|
||||
debug(adi) printf("adCmpChar()\n");
|
||||
len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
|
||||
if (!c)
|
||||
c = cast(int)a1.length - cast(int)a2.length;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
110
druntime/src/compiler/dmd/alloca.d
Normal file
110
druntime/src/compiler/dmd/alloca.d
Normal file
@@ -0,0 +1,110 @@
|
||||
/*_ _alloca.d
|
||||
* Copyright (C) 1990-2003 by Digital Mars, www.digitalmars.com
|
||||
* All Rights Reserved
|
||||
* Written by Walter Bright
|
||||
*/
|
||||
|
||||
module rt.alloca;
|
||||
|
||||
/+
|
||||
#if DOS386
|
||||
extern size_t _x386_break;
|
||||
#else
|
||||
extern size_t _pastdata;
|
||||
#endif
|
||||
+/
|
||||
|
||||
/*******************************************
|
||||
* Allocate data from the caller's stack frame.
|
||||
* This is a 'magic' function that needs help from the compiler to
|
||||
* work right, do not change its name, do not call it from other compilers.
|
||||
* Input:
|
||||
* nbytes number of bytes to allocate
|
||||
* ECX address of variable with # of bytes in locals
|
||||
* This is adjusted upon return to reflect the additional
|
||||
* size of the stack frame.
|
||||
* Returns:
|
||||
* EAX allocated data, null if stack overflows
|
||||
*/
|
||||
|
||||
extern (C) void* __alloca(int nbytes)
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked ;
|
||||
mov EDX,ECX ;
|
||||
mov EAX,4[ESP] ; // get nbytes
|
||||
push EBX ;
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
add EAX,3 ;
|
||||
and EAX,0xFFFFFFFC ; // round up to dword
|
||||
jnz Abegin ;
|
||||
mov EAX,4 ; // allow zero bytes allocation, 0 rounded to dword is 4..
|
||||
Abegin:
|
||||
mov ESI,EAX ; // ESI = nbytes
|
||||
neg EAX ;
|
||||
add EAX,ESP ; // EAX is now what the new ESP will be.
|
||||
jae Aoverflow ;
|
||||
}
|
||||
version (Windows)
|
||||
{
|
||||
asm
|
||||
{
|
||||
// We need to be careful about the guard page
|
||||
// Thus, for every 4k page, touch it to cause the OS to load it in.
|
||||
mov ECX,EAX ; // ECX is new location for stack
|
||||
mov EBX,ESI ; // EBX is size to "grow" stack
|
||||
L1:
|
||||
test [ECX+EBX],EBX ; // bring in page
|
||||
sub EBX,0x1000 ; // next 4K page down
|
||||
jae L1 ; // if more pages
|
||||
test [ECX],EBX ; // bring in last page
|
||||
}
|
||||
}
|
||||
version (DOS386)
|
||||
{
|
||||
asm
|
||||
{
|
||||
// is ESP off bottom?
|
||||
cmp EAX,_x386_break ;
|
||||
jbe Aoverflow ;
|
||||
}
|
||||
}
|
||||
version (Unix)
|
||||
{
|
||||
asm
|
||||
{
|
||||
cmp EAX,_pastdata ;
|
||||
jbe Aoverflow ; // Unlikely - ~2 Gbytes under UNIX
|
||||
}
|
||||
}
|
||||
asm
|
||||
{
|
||||
// Copy down to [ESP] the temps on the stack.
|
||||
// The number of temps is (EBP - ESP - locals).
|
||||
mov ECX,EBP ;
|
||||
sub ECX,ESP ;
|
||||
sub ECX,[EDX] ; // ECX = number of temps (bytes) to move.
|
||||
add [EDX],ESI ; // adjust locals by nbytes for next call to alloca()
|
||||
mov ESP,EAX ; // Set up new stack pointer.
|
||||
add EAX,ECX ; // Return value = ESP + temps.
|
||||
mov EDI,ESP ; // Destination of copy of temps.
|
||||
add ESI,ESP ; // Source of copy.
|
||||
shr ECX,2 ; // ECX to count of dwords in temps
|
||||
// Always at least 4 (nbytes, EIP, ESI,and EDI).
|
||||
rep ;
|
||||
movsd ;
|
||||
jmp done ;
|
||||
|
||||
Aoverflow:
|
||||
// Overflowed the stack. Return null
|
||||
xor EAX,EAX ;
|
||||
|
||||
done:
|
||||
pop ESI ;
|
||||
pop EDI ;
|
||||
pop EBX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
180
druntime/src/compiler/dmd/arrayassign.d
Normal file
180
druntime/src/compiler/dmd/arrayassign.d
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* http://www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
* Placed in the Public Domain
|
||||
*/
|
||||
module rt.arrayassign;
|
||||
|
||||
private
|
||||
{
|
||||
import util.string;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
debug(PRINTF) import stdc.stdio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does array assignment (not construction) from another
|
||||
* array of the same element type.
|
||||
* ti is the element type.
|
||||
* Handles overlapping copies.
|
||||
*/
|
||||
extern (C) void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
|
||||
{
|
||||
debug(PRINTF) printf("_d_arrayassign(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
char[10] tmp = void;
|
||||
string msg = "lengths don't match for array copy,"c;
|
||||
msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
/* Need a temporary buffer tmp[] big enough to hold one element
|
||||
*/
|
||||
void[16] buf = void;
|
||||
void[] tmp;
|
||||
if (element_size > buf.sizeof)
|
||||
tmp = alloca(element_size)[0 .. element_size];
|
||||
else
|
||||
tmp = buf;
|
||||
|
||||
|
||||
if (to.ptr <= from.ptr)
|
||||
{
|
||||
foreach (i; 0 .. to.length)
|
||||
{
|
||||
void* pto = to.ptr + i * element_size;
|
||||
void* pfrom = from.ptr + i * element_size;
|
||||
memcpy(tmp.ptr, pto, element_size);
|
||||
memcpy(pto, pfrom, element_size);
|
||||
ti.postblit(pto);
|
||||
ti.destroy(tmp.ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = to.length; i--; )
|
||||
{
|
||||
void* pto = to.ptr + i * element_size;
|
||||
void* pfrom = from.ptr + i * element_size;
|
||||
memcpy(tmp.ptr, pto, element_size);
|
||||
memcpy(pto, pfrom, element_size);
|
||||
ti.postblit(pto);
|
||||
ti.destroy(tmp.ptr);
|
||||
}
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does array initialization (not assignment) from another
|
||||
* array of the same element type.
|
||||
* ti is the element type.
|
||||
*/
|
||||
extern (C) void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
|
||||
{
|
||||
debug(PRINTF) printf("_d_arrayctor(from = %p,%d, to = %p,%d) size = %d\n", from.ptr, from.length, to.ptr, to.length, ti.tsize());
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
char[10] tmp = void;
|
||||
string msg = "lengths don't match for array initialization,"c;
|
||||
msg ~= tmp.intToString(to.length) ~ " = " ~ tmp.intToString(from.length);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
int i;
|
||||
try
|
||||
{
|
||||
for (i = 0; i < to.length; i++)
|
||||
{
|
||||
// Copy construction is defined as bit copy followed by postblit.
|
||||
memcpy(to.ptr + i * element_size, from.ptr + i * element_size, element_size);
|
||||
ti.postblit(to.ptr + i * element_size);
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
/* Destroy, in reverse order, what we've constructed so far
|
||||
*/
|
||||
while (i--)
|
||||
{
|
||||
ti.destroy(to.ptr + i * element_size);
|
||||
}
|
||||
|
||||
throw o;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do assignment to an array.
|
||||
* p[0 .. count] = value;
|
||||
*/
|
||||
extern (C) void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
|
||||
{
|
||||
void* pstart = p;
|
||||
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
//Need a temporary buffer tmp[] big enough to hold one element
|
||||
void[16] buf = void;
|
||||
void[] tmp;
|
||||
if (element_size > buf.sizeof)
|
||||
{
|
||||
tmp = alloca(element_size)[0 .. element_size];
|
||||
}
|
||||
else
|
||||
tmp = buf;
|
||||
|
||||
foreach (i; 0 .. count)
|
||||
{
|
||||
memcpy(tmp.ptr, p, element_size);
|
||||
memcpy(p, value, element_size);
|
||||
ti.postblit(p);
|
||||
ti.destroy(tmp.ptr);
|
||||
p += element_size;
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do construction of an array.
|
||||
* ti[count] p = value;
|
||||
*/
|
||||
extern (C) void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
|
||||
{
|
||||
void* pstart = p;
|
||||
auto element_size = ti.tsize();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (i; 0 .. count)
|
||||
{
|
||||
// Copy construction is defined as bit copy followed by postblit.
|
||||
memcpy(p, value, element_size);
|
||||
ti.postblit(p);
|
||||
p += element_size;
|
||||
}
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
// Destroy, in reverse order, what we've constructed so far
|
||||
while (p > pstart)
|
||||
{
|
||||
p -= element_size;
|
||||
ti.destroy(p);
|
||||
}
|
||||
|
||||
throw o;
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
1890
druntime/src/compiler/dmd/arraybyte.d
Normal file
1890
druntime/src/compiler/dmd/arraybyte.d
Normal file
File diff suppressed because it is too large
Load Diff
109
druntime/src/compiler/dmd/arraycast.d
Normal file
109
druntime/src/compiler/dmd/arraycast.d
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.arraycast;
|
||||
|
||||
/******************************************
|
||||
* Runtime helper to convert dynamic array of one
|
||||
* type to dynamic array of another.
|
||||
* Adjusts the length of the array.
|
||||
* Throws exception if new length is not aligned.
|
||||
*/
|
||||
|
||||
extern (C)
|
||||
|
||||
void[] _d_arraycast(size_t tsize, size_t fsize, void[] a)
|
||||
{
|
||||
auto length = a.length;
|
||||
|
||||
auto nbytes = length * fsize;
|
||||
if (nbytes % tsize != 0)
|
||||
{
|
||||
throw new Exception("array cast misalignment");
|
||||
}
|
||||
length = nbytes / tsize;
|
||||
*cast(size_t *)&a = length; // jam new length
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
byte[int.sizeof * 3] b;
|
||||
int[] i;
|
||||
short[] s;
|
||||
|
||||
i = cast(int[])b;
|
||||
assert(i.length == 3);
|
||||
|
||||
s = cast(short[])b;
|
||||
assert(s.length == 6);
|
||||
|
||||
s = cast(short[])i;
|
||||
assert(s.length == 6);
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Runtime helper to convert dynamic array of bits
|
||||
* dynamic array of another.
|
||||
* Adjusts the length of the array.
|
||||
* Throws exception if new length is not aligned.
|
||||
*/
|
||||
|
||||
version (none)
|
||||
{
|
||||
extern (C)
|
||||
|
||||
void[] _d_arraycast_frombit(uint tsize, void[] a)
|
||||
{
|
||||
uint length = a.length;
|
||||
|
||||
if (length & 7)
|
||||
{
|
||||
throw new Exception("bit[] array cast misalignment");
|
||||
}
|
||||
length /= 8 * tsize;
|
||||
*cast(size_t *)&a = length; // jam new length
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
version (D_Bits)
|
||||
{
|
||||
bit[int.sizeof * 3 * 8] b;
|
||||
int[] i;
|
||||
short[] s;
|
||||
|
||||
i = cast(int[])b;
|
||||
assert(i.length == 3);
|
||||
|
||||
s = cast(short[])b;
|
||||
assert(s.length == 6);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
61
druntime/src/compiler/dmd/arraycat.d
Normal file
61
druntime/src/compiler/dmd/arraycat.d
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.arraycat;
|
||||
|
||||
private
|
||||
{
|
||||
import stdc.string;
|
||||
debug import stdc.stdio;
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
|
||||
{
|
||||
debug printf("f = %p,%d, t = %p,%d, size = %d\n",
|
||||
from.ptr, from.length, to.ptr, to.length, size);
|
||||
|
||||
if (to.length != from.length)
|
||||
{
|
||||
throw new Exception("lengths don't match for array copy");
|
||||
}
|
||||
else if (to.ptr + to.length * size <= from.ptr ||
|
||||
from.ptr + from.length * size <= to.ptr)
|
||||
{
|
||||
memcpy(to.ptr, from.ptr, to.length * size);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("overlapping array copy");
|
||||
}
|
||||
return to;
|
||||
}
|
||||
1714
druntime/src/compiler/dmd/arraydouble.d
Normal file
1714
druntime/src/compiler/dmd/arraydouble.d
Normal file
File diff suppressed because it is too large
Load Diff
2303
druntime/src/compiler/dmd/arrayfloat.d
Normal file
2303
druntime/src/compiler/dmd/arrayfloat.d
Normal file
File diff suppressed because it is too large
Load Diff
2427
druntime/src/compiler/dmd/arrayint.d
Normal file
2427
druntime/src/compiler/dmd/arrayint.d
Normal file
File diff suppressed because it is too large
Load Diff
234
druntime/src/compiler/dmd/arrayreal.d
Normal file
234
druntime/src/compiler/dmd/arrayreal.d
Normal file
@@ -0,0 +1,234 @@
|
||||
/***************************
|
||||
* D programming language http://www.digitalmars.com/d/
|
||||
* Runtime support for double array operations.
|
||||
* Placed in public domain.
|
||||
*/
|
||||
|
||||
module rt.arrayreal;
|
||||
|
||||
import util.cpuid;
|
||||
|
||||
version (Unittest)
|
||||
{
|
||||
/* This is so unit tests will test every CPU variant
|
||||
*/
|
||||
int cpuid;
|
||||
const int CPUID_MAX = 1;
|
||||
bool mmx() { return cpuid == 1 && util.cpuid.mmx(); }
|
||||
bool sse() { return cpuid == 2 && util.cpuid.sse(); }
|
||||
bool sse2() { return cpuid == 3 && util.cpuid.sse2(); }
|
||||
bool amd3dnow() { return cpuid == 4 && util.cpuid.amd3dnow(); }
|
||||
}
|
||||
else
|
||||
{
|
||||
alias util.cpuid.mmx mmx;
|
||||
alias util.cpuid.sse sse;
|
||||
alias util.cpuid.sse2 sse2;
|
||||
alias util.cpuid.amd3dnow amd3dnow;
|
||||
}
|
||||
|
||||
//version = log;
|
||||
|
||||
bool disjoint(T)(T[] a, T[] b)
|
||||
{
|
||||
return (a.ptr + a.length <= b.ptr || b.ptr + b.length <= a.ptr);
|
||||
}
|
||||
|
||||
alias real T;
|
||||
|
||||
extern (C):
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] = b[] + c[]
|
||||
*/
|
||||
|
||||
T[] _arraySliceSliceAddSliceAssign_r(T[] a, T[] c, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length && b.length == c.length);
|
||||
assert(disjoint(a, b));
|
||||
assert(disjoint(a, c));
|
||||
assert(disjoint(b, c));
|
||||
}
|
||||
body
|
||||
{
|
||||
for (int i = 0; i < a.length; i++)
|
||||
a[i] = b[i] + c[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceSliceAddSliceAssign_r unittest\n");
|
||||
for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
c[] = a[] + b[];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
if (c[i] != cast(T)(a[i] + b[i]))
|
||||
{
|
||||
printf("[%d]: %Lg != %Lg + %Lg\n", i, c[i], a[i], b[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] = b[] - c[]
|
||||
*/
|
||||
|
||||
T[] _arraySliceSliceMinSliceAssign_r(T[] a, T[] c, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length && b.length == c.length);
|
||||
assert(disjoint(a, b));
|
||||
assert(disjoint(a, c));
|
||||
assert(disjoint(b, c));
|
||||
}
|
||||
body
|
||||
{
|
||||
for (int i = 0; i < a.length; i++)
|
||||
a[i] = b[i] - c[i];
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceSliceMinSliceAssign_r unittest\n");
|
||||
for (cpuid = 0; cpuid < CPUID_MAX; cpuid++)
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
c[] = a[] - b[];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
if (c[i] != cast(T)(a[i] - b[i]))
|
||||
{
|
||||
printf("[%d]: %Lg != %Lg - %Lg\n", i, c[i], a[i], b[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] -= b[] * value
|
||||
*/
|
||||
|
||||
T[] _arraySliceExpMulSliceMinass_r(T[] a, T value, T[] b)
|
||||
{
|
||||
return _arraySliceExpMulSliceAddass_r(a, -value, b);
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Computes:
|
||||
* a[] += b[] * value
|
||||
*/
|
||||
|
||||
T[] _arraySliceExpMulSliceAddass_r(T[] a, T value, T[] b)
|
||||
in
|
||||
{
|
||||
assert(a.length == b.length);
|
||||
assert(disjoint(a, b));
|
||||
}
|
||||
body
|
||||
{
|
||||
auto aptr = a.ptr;
|
||||
auto aend = aptr + a.length;
|
||||
auto bptr = b.ptr;
|
||||
|
||||
// Handle remainder
|
||||
while (aptr < aend)
|
||||
*aptr++ += *bptr++ * value;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
printf("_arraySliceExpMulSliceAddass_r unittest\n");
|
||||
|
||||
cpuid = 1;
|
||||
{
|
||||
version (log) printf(" cpuid %d\n", cpuid);
|
||||
|
||||
for (int j = 0; j < 1; j++)
|
||||
{
|
||||
const int dim = 67;
|
||||
T[] a = new T[dim + j]; // aligned on 16 byte boundary
|
||||
a = a[j .. dim + j]; // misalign for second iteration
|
||||
T[] b = new T[dim + j];
|
||||
b = b[j .. dim + j];
|
||||
T[] c = new T[dim + j];
|
||||
c = c[j .. dim + j];
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{ a[i] = cast(T)i;
|
||||
b[i] = cast(T)(i + 7);
|
||||
c[i] = cast(T)(i * 2);
|
||||
}
|
||||
|
||||
b[] = c[];
|
||||
c[] += a[] * 6;
|
||||
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
//printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
|
||||
if (c[i] != cast(T)(b[i] + a[i] * 6))
|
||||
{
|
||||
printf("[%d]: %Lg ?= %Lg + %Lg * 6\n", i, c[i], b[i], a[i]);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2300
druntime/src/compiler/dmd/arrayshort.d
Normal file
2300
druntime/src/compiler/dmd/arrayshort.d
Normal file
File diff suppressed because it is too large
Load Diff
184
druntime/src/compiler/dmd/cast_.d
Normal file
184
druntime/src/compiler/dmd/cast_.d
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.cast_;
|
||||
|
||||
extern (C):
|
||||
|
||||
/******************************************
|
||||
* Given a pointer:
|
||||
* If it is an Object, return that Object.
|
||||
* If it is an interface, return the Object implementing the interface.
|
||||
* If it is null, return null.
|
||||
* Else, undefined crash
|
||||
*/
|
||||
|
||||
Object _d_toObject(void* p)
|
||||
{ Object o;
|
||||
|
||||
if (p)
|
||||
{
|
||||
o = cast(Object)p;
|
||||
ClassInfo oc = o.classinfo;
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
/* Interface.offset lines up with ClassInfo.name.ptr,
|
||||
* so we rely on pointers never being less than 64K,
|
||||
* and Objects never being greater.
|
||||
*/
|
||||
if (pi.offset < 0x10000)
|
||||
{
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Attempts to cast Object o to class c.
|
||||
* Returns o if successful, null if not.
|
||||
*/
|
||||
|
||||
Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{ Object o;
|
||||
|
||||
//printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name);
|
||||
if (p)
|
||||
{
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
//printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
return _d_dynamic_cast(o, c);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{ ClassInfo oc;
|
||||
size_t offset = 0;
|
||||
|
||||
//printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name);
|
||||
|
||||
if (o)
|
||||
{
|
||||
oc = o.classinfo;
|
||||
if (_d_isbaseof2(oc, c, offset))
|
||||
{
|
||||
//printf("\toffset = %d\n", offset);
|
||||
o = cast(Object)(cast(void*)o + offset);
|
||||
}
|
||||
else
|
||||
o = null;
|
||||
}
|
||||
//printf("\tresult = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c)
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (_d_isbaseof2(ic, c, offset))
|
||||
{ offset = oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c || _d_isbaseof(ic, c))
|
||||
return 1;
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Find the vtbl[] associated with Interface ic.
|
||||
*/
|
||||
|
||||
void *_d_interface_vtbl(ClassInfo ic, Object o)
|
||||
{ int i;
|
||||
ClassInfo oc;
|
||||
|
||||
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
|
||||
|
||||
assert(o);
|
||||
|
||||
oc = o.classinfo;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo oic;
|
||||
|
||||
oic = oc.interfaces[i].classinfo;
|
||||
if (oic is ic)
|
||||
{
|
||||
return cast(void *)oc.interfaces[i].vtbl;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
218
druntime/src/compiler/dmd/cmath2.d
Normal file
218
druntime/src/compiler/dmd/cmath2.d
Normal file
@@ -0,0 +1,218 @@
|
||||
|
||||
// Copyright (C) 2001-2003 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// www.digitalmars.com
|
||||
|
||||
// Runtime support for complex arithmetic code generation
|
||||
// (for linux)
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.cmath2;
|
||||
|
||||
private import stdc.math;
|
||||
|
||||
extern (C):
|
||||
|
||||
/****************************
|
||||
* Multiply two complex floating point numbers, x and y.
|
||||
* Input:
|
||||
* x.re ST3
|
||||
* x.im ST2
|
||||
* y.re ST1
|
||||
* y.im ST0
|
||||
* Output:
|
||||
* ST1 real part
|
||||
* ST0 imaginary part
|
||||
*/
|
||||
|
||||
void _Cmul()
|
||||
{
|
||||
// p.re = x.re * y.re - x.im * y.im;
|
||||
// p.im = x.im * y.re + x.re * y.im;
|
||||
asm
|
||||
{ naked ;
|
||||
fld ST(1) ; // x.re
|
||||
fmul ST,ST(4) ; // ST0 = x.re * y.re
|
||||
|
||||
fld ST(1) ; // y.im
|
||||
fmul ST,ST(4) ; // ST0 = x.im * y.im
|
||||
|
||||
fsubp ST(1),ST ; // ST0 = x.re * y.re - x.im * y.im
|
||||
|
||||
fld ST(3) ; // x.im
|
||||
fmul ST,ST(3) ; // ST0 = x.im * y.re
|
||||
|
||||
fld ST(5) ; // x.re
|
||||
fmul ST,ST(3) ; // ST0 = x.re * y.im
|
||||
|
||||
faddp ST(1),ST ; // ST0 = x.im * y.re + x.re * y.im
|
||||
|
||||
fxch ST(4),ST ;
|
||||
fstp ST(0) ;
|
||||
fxch ST(4),ST ;
|
||||
fstp ST(0) ;
|
||||
fstp ST(0) ;
|
||||
fstp ST(0) ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
/+
|
||||
if (isnan(x) && isnan(y))
|
||||
{
|
||||
// Recover infinities that computed as NaN+ iNaN ...
|
||||
int recalc = 0;
|
||||
if ( isinf( a) || isinf( b) )
|
||||
{ // z is infinite
|
||||
// "Box" the infinity and change NaNs in the other factor to 0
|
||||
a = copysignl( isinf( a) ? 1.0 : 0.0, a);
|
||||
b = copysignl( isinf( b) ? 1.0 : 0.0, b);
|
||||
if (isnan( c)) c = copysignl( 0.0, c);
|
||||
if (isnan( d)) d = copysignl( 0.0, d);
|
||||
recalc = 1;
|
||||
}
|
||||
if (isinf(c) || isinf(d))
|
||||
{ // w is infinite
|
||||
// "Box" the infinity and change NaNs in the other factor to 0
|
||||
c = copysignl( isinf( c) ? 1.0 : 0.0, c);
|
||||
d = copysignl( isinf( d) ? 1.0 : 0.0, d);
|
||||
if (isnan( a)) a = copysignl( 0.0, a);
|
||||
if (isnan( b)) b = copysignl( 0.0, b);
|
||||
recalc = 1;
|
||||
}
|
||||
if (!recalc && (isinf(ac) || isinf(bd) ||
|
||||
isinf(ad) || isinf(bc)))
|
||||
{
|
||||
// Recover infinities from overflow by changing NaNs to 0 ...
|
||||
if (isnan( a)) a = copysignl( 0.0, a);
|
||||
if (isnan( b)) b = copysignl( 0.0, b);
|
||||
if (isnan( c)) c = copysignl( 0.0, c);
|
||||
if (isnan( d)) d = copysignl( 0.0, d);
|
||||
recalc = 1;
|
||||
}
|
||||
if (recalc)
|
||||
{
|
||||
x = INFINITY * (a * c - b * d);
|
||||
y = INFINITY * (a * d + b * c);
|
||||
}
|
||||
}
|
||||
+/
|
||||
}
|
||||
|
||||
/****************************
|
||||
* Divide two complex floating point numbers, x / y.
|
||||
* Input:
|
||||
* x.re ST3
|
||||
* x.im ST2
|
||||
* y.re ST1
|
||||
* y.im ST0
|
||||
* Output:
|
||||
* ST1 real part
|
||||
* ST0 imaginary part
|
||||
*/
|
||||
|
||||
void _Cdiv()
|
||||
{
|
||||
real x_re, x_im;
|
||||
real y_re, y_im;
|
||||
real q_re, q_im;
|
||||
real r;
|
||||
real den;
|
||||
|
||||
asm
|
||||
{
|
||||
fstp y_im ;
|
||||
fstp y_re ;
|
||||
fstp x_im ;
|
||||
fstp x_re ;
|
||||
}
|
||||
|
||||
if (fabs(y_re) < fabs(y_im))
|
||||
{
|
||||
r = y_re / y_im;
|
||||
den = y_im + r * y_re;
|
||||
q_re = (x_re * r + x_im) / den;
|
||||
q_im = (x_im * r - x_re) / den;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = y_im / y_re;
|
||||
den = y_re + r * y_im;
|
||||
q_re = (x_re + r * x_im) / den;
|
||||
q_im = (x_im - r * x_re) / den;
|
||||
}
|
||||
//printf("q.re = %g, q.im = %g\n", (double)q_re, (double)q_im);
|
||||
/+
|
||||
if (isnan(q_re) && isnan(q_im))
|
||||
{
|
||||
real denom = y_re * y_re + y_im * y_im;
|
||||
|
||||
// non-zero / zero
|
||||
if (denom == 0.0 && (!isnan(x_re) || !isnan(x_im)))
|
||||
{
|
||||
q_re = copysignl(INFINITY, y_re) * x_re;
|
||||
q_im = copysignl(INFINITY, y_re) * x_im;
|
||||
}
|
||||
// infinite / finite
|
||||
else if ((isinf(x_re) || isinf(x_im)) && isfinite(y_re) && isfinite(y_im))
|
||||
{
|
||||
x_re = copysignl(isinf(x_re) ? 1.0 : 0.0, x_re);
|
||||
x_im = copysignl(isinf(x_im) ? 1.0 : 0.0, x_im);
|
||||
q_re = INFINITY * (x_re * y_re + x_im * y_im);
|
||||
q_im = INFINITY * (x_im * y_re - x_re * y_im);
|
||||
}
|
||||
// finite / infinite
|
||||
else if (isinf(logbw) && isfinite(x_re) && isfinite(x_im))
|
||||
{
|
||||
y_re = copysignl(isinf(y_re) ? 1.0 : 0.0, y_re);
|
||||
y_im = copysignl(isinf(y_im) ? 1.0 : 0.0, y_im);
|
||||
q_re = 0.0 * (x_re * y_re + x_im * y_im);
|
||||
q_im = 0.0 * (x_im * y_re - x_re * y_im);
|
||||
}
|
||||
}
|
||||
return q_re + q_im * 1.0i;
|
||||
+/
|
||||
asm
|
||||
{
|
||||
fld q_re;
|
||||
fld q_im;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************
|
||||
* Compare two complex floating point numbers, x and y.
|
||||
* Input:
|
||||
* x.re ST3
|
||||
* x.im ST2
|
||||
* y.re ST1
|
||||
* y.im ST0
|
||||
* Output:
|
||||
* 8087 stack is cleared
|
||||
* flags set
|
||||
*/
|
||||
|
||||
void _Ccmp()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
fucomp ST(2) ; // compare x.im and y.im
|
||||
fstsw AX ;
|
||||
sahf ;
|
||||
jne L1 ;
|
||||
jp L1 ; // jmp if NAN
|
||||
fucomp ST(2) ; // compare x.re and y.re
|
||||
fstsw AX ;
|
||||
sahf ;
|
||||
fstp ST(0) ; // pop
|
||||
fstp ST(0) ; // pop
|
||||
ret ;
|
||||
|
||||
L1:
|
||||
fstp ST(0) ; // pop
|
||||
fstp ST(0) ; // pop
|
||||
fstp ST(0) ; // pop
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
36
druntime/src/compiler/dmd/compiler.d
Normal file
36
druntime/src/compiler/dmd/compiler.d
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
/* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
* Placed into Public Domain
|
||||
*/
|
||||
|
||||
module rt.compiler;
|
||||
|
||||
// Identify the compiler used and its various features.
|
||||
|
||||
const
|
||||
{
|
||||
// Vendor specific string naming the compiler
|
||||
char[] name = "Digital Mars D";
|
||||
|
||||
// Master list of D compiler vendors
|
||||
enum Vendor
|
||||
{
|
||||
DigitalMars = 1
|
||||
}
|
||||
|
||||
// Which vendor we are
|
||||
Vendor vendor = Vendor.DigitalMars;
|
||||
|
||||
|
||||
// The vendor specific version number, as in
|
||||
// version_major.version_minor
|
||||
uint version_major = 0;
|
||||
uint version_minor = 0;
|
||||
|
||||
|
||||
// The version of the D Programming Language Specification
|
||||
// Supported by the compiler
|
||||
uint D_major = 0;
|
||||
uint D_minor = 0;
|
||||
}
|
||||
107
druntime/src/compiler/dmd/complex.c
Normal file
107
druntime/src/compiler/dmd/complex.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Placed into the public domain.
|
||||
* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef struct Complex
|
||||
{
|
||||
long double re;
|
||||
long double im;
|
||||
} Complex;
|
||||
|
||||
Complex _complex_div(Complex x, Complex y)
|
||||
{
|
||||
Complex q;
|
||||
long double r;
|
||||
long double den;
|
||||
|
||||
if (fabs(y.re) < fabs(y.im))
|
||||
{
|
||||
r = y.re / y.im;
|
||||
den = y.im + r * y.re;
|
||||
q.re = (x.re * r + x.im) / den;
|
||||
q.im = (x.im * r - x.re) / den;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = y.im / y.re;
|
||||
den = y.re + r * y.im;
|
||||
q.re = (x.re + r * x.im) / den;
|
||||
q.im = (x.im - r * x.re) / den;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
Complex _complex_mul(Complex x, Complex y)
|
||||
{
|
||||
Complex p;
|
||||
|
||||
p.re = x.re * y.re - x.im * y.im;
|
||||
p.im = x.im * y.re + x.re * y.im;
|
||||
return p;
|
||||
}
|
||||
|
||||
long double _complex_abs(Complex z)
|
||||
{
|
||||
long double x,y,ans,temp;
|
||||
|
||||
x = fabs(z.re);
|
||||
y = fabs(z.im);
|
||||
if (x == 0)
|
||||
ans = y;
|
||||
else if (y == 0)
|
||||
ans = x;
|
||||
else if (x > y)
|
||||
{
|
||||
temp = y / x;
|
||||
ans = x * sqrt(1 + temp * temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = x / y;
|
||||
ans = y * sqrt(1 + temp * temp);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
Complex _complex_sqrt(Complex z)
|
||||
{
|
||||
Complex c;
|
||||
long double x,y,w,r;
|
||||
|
||||
if (z.re == 0 && z.im == 0)
|
||||
{
|
||||
c.re = 0;
|
||||
c.im = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = fabs(z.re);
|
||||
y = fabs(z.im);
|
||||
if (x >= y)
|
||||
{
|
||||
r = y / x;
|
||||
w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
|
||||
}
|
||||
else
|
||||
{
|
||||
r = x / y;
|
||||
w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
|
||||
}
|
||||
if (z.re >= 0)
|
||||
{
|
||||
c.re = w;
|
||||
c.im = z.im / (w + w);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.im = (z.im >= 0) ? w : -w;
|
||||
c.re = z.im / (c.im + c.im);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
373
druntime/src/compiler/dmd/cover.d
Normal file
373
druntime/src/compiler/dmd/cover.d
Normal file
@@ -0,0 +1,373 @@
|
||||
/**
|
||||
* Code coverage analyzer.
|
||||
*
|
||||
* Bugs:
|
||||
* $(UL
|
||||
* $(LI the execution counters are 32 bits in size, and can overflow)
|
||||
* $(LI inline asm statements are not counted)
|
||||
* )
|
||||
*
|
||||
* Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com. All rights reserved.
|
||||
* License: BSD style: $(LICENSE)
|
||||
* Authors: Walter Bright, Sean Kelly
|
||||
*/
|
||||
|
||||
module rt.cover;
|
||||
|
||||
private
|
||||
{
|
||||
version( Windows )
|
||||
import sys.windows.windows;
|
||||
else version( Posix )
|
||||
{
|
||||
import stdc.posix.fcntl;
|
||||
import stdc.posix.unistd;
|
||||
}
|
||||
import core.bitmanip;
|
||||
import stdc.stdio;
|
||||
import util.utf;
|
||||
|
||||
struct BitArray
|
||||
{
|
||||
size_t len;
|
||||
uint* ptr;
|
||||
|
||||
bool opIndex( size_t i )
|
||||
in
|
||||
{
|
||||
assert( i < len );
|
||||
}
|
||||
body
|
||||
{
|
||||
return cast(bool) bt( ptr, i );
|
||||
}
|
||||
}
|
||||
|
||||
struct Cover
|
||||
{
|
||||
char[] filename;
|
||||
BitArray valid;
|
||||
uint[] data;
|
||||
}
|
||||
|
||||
Cover[] gdata;
|
||||
char[] srcpath;
|
||||
char[] dstpath;
|
||||
bool merge;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set path to where source files are located.
|
||||
*
|
||||
* Params:
|
||||
* pathname = The new path name.
|
||||
*/
|
||||
extern (C) void dmd_coverSourcePath( char[] pathname )
|
||||
{
|
||||
srcpath = pathname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set path to where listing files are to be written.
|
||||
*
|
||||
* Params:
|
||||
* pathname = The new path name.
|
||||
*/
|
||||
extern (C) void dmd_coverDestPath( char[] pathname )
|
||||
{
|
||||
dstpath = pathname;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set merge mode.
|
||||
*
|
||||
* Params:
|
||||
* flag = true means new data is summed with existing data in the listing
|
||||
* file; false means a new listing file is always created.
|
||||
*/
|
||||
extern (C) void dmd_coverSetMerge( bool flag )
|
||||
{
|
||||
merge = flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The coverage callback.
|
||||
*
|
||||
* Params:
|
||||
* filename = The name of the coverage file.
|
||||
* valid = ???
|
||||
* data = ???
|
||||
*/
|
||||
extern (C) void _d_cover_register( char[] filename, BitArray valid, uint[] data )
|
||||
{
|
||||
Cover c;
|
||||
|
||||
c.filename = filename;
|
||||
c.valid = valid;
|
||||
c.data = data;
|
||||
gdata ~= c;
|
||||
}
|
||||
|
||||
|
||||
static ~this()
|
||||
{
|
||||
const NUMLINES = 16384 - 1;
|
||||
const NUMCHARS = 16384 * 16 - 1;
|
||||
|
||||
char[] srcbuf = new char[NUMCHARS];
|
||||
char[][] srclines = new char[][NUMLINES];
|
||||
char[] lstbuf = new char[NUMCHARS];
|
||||
char[][] lstlines = new char[][NUMLINES];
|
||||
|
||||
foreach( Cover c; gdata )
|
||||
{
|
||||
if( !readFile( appendFN( srcpath, c.filename ), srcbuf ) )
|
||||
continue;
|
||||
splitLines( srcbuf, srclines );
|
||||
|
||||
if( merge )
|
||||
{
|
||||
if( !readFile( c.filename ~ ".lst", lstbuf ) )
|
||||
break;
|
||||
splitLines( lstbuf, lstlines );
|
||||
|
||||
for( size_t i = 0; i < lstlines.length; ++i )
|
||||
{
|
||||
if( i >= c.data.length )
|
||||
break;
|
||||
|
||||
int count = 0;
|
||||
|
||||
foreach( char c2; lstlines[i] )
|
||||
{
|
||||
switch( c2 )
|
||||
{
|
||||
case ' ':
|
||||
continue;
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
count = count * 10 + c2 - '0';
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
c.data[i] += count;
|
||||
}
|
||||
}
|
||||
|
||||
FILE* flst = fopen( (c.filename ~ ".lst").ptr, "wb" );
|
||||
|
||||
if( !flst )
|
||||
continue; //throw new Exception( "Error opening file for write: " ~ lstfn );
|
||||
|
||||
uint nno;
|
||||
uint nyes;
|
||||
|
||||
for( int i = 0; i < c.data.length; i++ )
|
||||
{
|
||||
if( i < srclines.length )
|
||||
{
|
||||
uint n = c.data[i];
|
||||
char[] line = srclines[i];
|
||||
|
||||
line = expandTabs( line );
|
||||
|
||||
if( n == 0 )
|
||||
{
|
||||
if( c.valid[i] )
|
||||
{
|
||||
nno++;
|
||||
fprintf( flst, "0000000|%.*s\n", line );
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( flst, " |%.*s\n", line );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nyes++;
|
||||
fprintf( flst, "%7u|%.*s\n", n, line );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( nyes + nno ) // no divide by 0 bugs
|
||||
{
|
||||
fprintf( flst, "%.*s is %d%% covered\n", c.filename, ( nyes * 100 ) / ( nyes + nno ) );
|
||||
}
|
||||
fclose( flst );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char[] appendFN( char[] path, char[] name )
|
||||
{
|
||||
version( Windows )
|
||||
const char sep = '\\';
|
||||
else
|
||||
const char sep = '/';
|
||||
|
||||
char[] dest = path;
|
||||
|
||||
if( dest && dest[$ - 1] != sep )
|
||||
dest ~= sep;
|
||||
dest ~= name;
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
bool readFile( char[] name, inout char[] buf )
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
auto wnamez = toUTF16z( name );
|
||||
HANDLE file = CreateFileW( wnamez,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
null,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
cast(HANDLE) null );
|
||||
|
||||
delete wnamez;
|
||||
if( file == INVALID_HANDLE_VALUE )
|
||||
return false;
|
||||
scope( exit ) CloseHandle( file );
|
||||
|
||||
DWORD num = 0;
|
||||
DWORD pos = 0;
|
||||
|
||||
buf.length = 4096;
|
||||
while( true )
|
||||
{
|
||||
if( !ReadFile( file, &buf[pos], cast(DWORD)( buf.length - pos ), &num, null ) )
|
||||
return false;
|
||||
if( !num )
|
||||
break;
|
||||
pos += num;
|
||||
buf.length = pos * 2;
|
||||
}
|
||||
buf.length = pos;
|
||||
return true;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
char[] namez = new char[name.length + 1];
|
||||
namez[0 .. name.length] = name;
|
||||
namez[$ - 1] = 0;
|
||||
int file = open( namez.ptr, O_RDONLY );
|
||||
|
||||
delete namez;
|
||||
if( file == -1 )
|
||||
return false;
|
||||
scope( exit ) close( file );
|
||||
|
||||
int num = 0;
|
||||
uint pos = 0;
|
||||
|
||||
buf.length = 4096;
|
||||
while( true )
|
||||
{
|
||||
num = read( file, &buf[pos], cast(uint)( buf.length - pos ) );
|
||||
if( num == -1 )
|
||||
return false;
|
||||
if( !num )
|
||||
break;
|
||||
pos += num;
|
||||
buf.length = pos * 2;
|
||||
}
|
||||
buf.length = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void splitLines( char[] buf, inout char[][] lines )
|
||||
{
|
||||
size_t beg = 0,
|
||||
pos = 0;
|
||||
|
||||
lines.length = 0;
|
||||
for( ; pos < buf.length; ++pos )
|
||||
{
|
||||
char c = buf[pos];
|
||||
|
||||
switch( buf[pos] )
|
||||
{
|
||||
case '\r':
|
||||
case '\n':
|
||||
lines ~= buf[beg .. pos];
|
||||
beg = pos + 1;
|
||||
if( buf[pos] == '\r' && pos < buf.length - 1 && buf[pos + 1] == '\n' )
|
||||
++pos, ++beg;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( beg != pos )
|
||||
{
|
||||
lines ~= buf[beg .. pos];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char[] expandTabs( char[] string, int tabsize = 8 )
|
||||
{
|
||||
const dchar LS = '\u2028'; // UTF line separator
|
||||
const dchar PS = '\u2029'; // UTF paragraph separator
|
||||
|
||||
bool changes = false;
|
||||
char[] result = string;
|
||||
int column;
|
||||
int nspaces;
|
||||
|
||||
foreach( size_t i, dchar c; string )
|
||||
{
|
||||
switch( c )
|
||||
{
|
||||
case '\t':
|
||||
nspaces = tabsize - (column % tabsize);
|
||||
if( !changes )
|
||||
{
|
||||
changes = true;
|
||||
result = null;
|
||||
result.length = string.length + nspaces - 1;
|
||||
result.length = i + nspaces;
|
||||
result[0 .. i] = string[0 .. i];
|
||||
result[i .. i + nspaces] = ' ';
|
||||
}
|
||||
else
|
||||
{ int j = result.length;
|
||||
result.length = j + nspaces;
|
||||
result[j .. j + nspaces] = ' ';
|
||||
}
|
||||
column += nspaces;
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
case '\n':
|
||||
case PS:
|
||||
case LS:
|
||||
column = 0;
|
||||
goto L1;
|
||||
|
||||
default:
|
||||
column++;
|
||||
L1:
|
||||
if (changes)
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
result ~= c;
|
||||
else
|
||||
encode(result, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
159
druntime/src/compiler/dmd/critical.c
Normal file
159
druntime/src/compiler/dmd/critical.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/* ================================= Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
CRITICAL_SECTION cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static volatile int inited;
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs->next)
|
||||
{
|
||||
EnterCriticalSection(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
InitializeCriticalSection(&dcs->cs);
|
||||
}
|
||||
LeaveCriticalSection(&critical_section.cs);
|
||||
}
|
||||
EnterCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
LeaveCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&critical_section.cs);
|
||||
dcs_list = &critical_section;
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
while (dcs_list)
|
||||
{
|
||||
DeleteCriticalSection(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ================================= linux ============================ */
|
||||
|
||||
#if linux
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
pthread_mutex_t cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static pthread_mutexattr_t _criticals_attr;
|
||||
|
||||
void _STI_critical_init(void);
|
||||
void _STD_critical_term(void);
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ _STI_critical_init();
|
||||
atexit(_STD_critical_term);
|
||||
}
|
||||
//printf("_d_criticalenter(dcs = x%x)\n", dcs);
|
||||
if (!dcs->next)
|
||||
{
|
||||
pthread_mutex_lock(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
pthread_mutex_init(&dcs->cs, &_criticals_attr);
|
||||
}
|
||||
pthread_mutex_unlock(&critical_section.cs);
|
||||
}
|
||||
pthread_mutex_lock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
|
||||
pthread_mutex_unlock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ //printf("_STI_critical_init()\n");
|
||||
pthread_mutexattr_init(&_criticals_attr);
|
||||
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
|
||||
// The global critical section doesn't need to be recursive
|
||||
pthread_mutex_init(&critical_section.cs, 0);
|
||||
dcs_list = &critical_section;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (dcs_list)
|
||||
{ //printf("_STI_critical_term()\n");
|
||||
while (dcs_list)
|
||||
{
|
||||
//printf("\tlooping... %x\n", dcs_list);
|
||||
pthread_mutex_destroy(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
662
druntime/src/compiler/dmd/deh.c
Normal file
662
druntime/src/compiler/dmd/deh.c
Normal file
@@ -0,0 +1,662 @@
|
||||
//
|
||||
// Copyright (c) 1999-2003 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
// Exception handling support
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* ======================== Win32 =============================== */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <excpt.h>
|
||||
#include <windows.h>
|
||||
|
||||
//#include "\sc\src\include\ehsup.h"
|
||||
|
||||
/*** From Digital Mars C runtime library ***/
|
||||
EXCEPTION_DISPOSITION __cdecl _local_except_handler (EXCEPTION_RECORD *ExceptionRecord,
|
||||
void* EstablisherFrame,
|
||||
void *ContextRecord,
|
||||
void *DispatcherContext
|
||||
);
|
||||
void __cdecl _global_unwind(void *frame,EXCEPTION_RECORD *eRecord);
|
||||
#define EXCEPTION_UNWIND 6 // Flag to indicate if the system is unwinding
|
||||
|
||||
extern DWORD _except_list;
|
||||
/*** ***/
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
extern ClassInfo D6object9Throwable7__ClassZ;
|
||||
#define _Class_9Throwable D6object9Throwable7__ClassZ;
|
||||
|
||||
extern ClassInfo D6object5Error7__ClassZ;
|
||||
#define _Class_5Error D6object5Error7__ClassZ
|
||||
|
||||
typedef int (__pascal *fp_t)(); // function pointer in ambient memory model
|
||||
|
||||
// The layout of DEstablisherFrame is the same for C++
|
||||
|
||||
struct DEstablisherFrame
|
||||
{
|
||||
void *prev; // pointer to previous exception list
|
||||
void *handler; // pointer to routine for exception handler
|
||||
DWORD table_index; // current index into handler_info[]
|
||||
DWORD ebp; // this is EBP of routine
|
||||
};
|
||||
|
||||
struct DHandlerInfo
|
||||
{
|
||||
int prev_index; // previous table index
|
||||
unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch)
|
||||
void *finally_code; // pointer to finally code to execute
|
||||
// (!=0 if try-finally)
|
||||
};
|
||||
|
||||
// Address of DHandlerTable is passed in EAX to _d_framehandler()
|
||||
|
||||
struct DHandlerTable
|
||||
{
|
||||
void *fptr; // pointer to start of function
|
||||
unsigned espoffset; // offset of ESP from EBP
|
||||
unsigned retoffset; // offset from start of function to return code
|
||||
struct DHandlerInfo handler_info[1];
|
||||
};
|
||||
|
||||
struct DCatchBlock
|
||||
{
|
||||
ClassInfo *type; // catch type
|
||||
unsigned bpoffset; // EBP offset of catch var
|
||||
void *code; // catch handler code
|
||||
};
|
||||
|
||||
// Create one of these for each try-catch
|
||||
struct DCatchInfo
|
||||
{
|
||||
unsigned ncatches; // number of catch blocks
|
||||
struct DCatchBlock catch_block[1]; // data for each catch block
|
||||
};
|
||||
|
||||
// Macro to make our own exception code
|
||||
#define MAKE_EXCEPTION_CODE(severity, facility, exception) \
|
||||
(((severity) << 30) | (1 << 29) | (0 << 28) | ((facility) << 16) | (exception))
|
||||
|
||||
#define STATUS_DIGITAL_MARS_D_EXCEPTION MAKE_EXCEPTION_CODE(3,'D',1)
|
||||
|
||||
Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record);
|
||||
void __cdecl _d_local_unwind(struct DHandlerTable *handler_table, struct DEstablisherFrame *frame, int stop_index);
|
||||
|
||||
|
||||
/***********************************
|
||||
* The frame handler, this is called for each frame that has been registered
|
||||
* in the OS except_list.
|
||||
* Input:
|
||||
* EAX the handler table for the frame
|
||||
*/
|
||||
|
||||
EXCEPTION_DISPOSITION _d_framehandler(
|
||||
EXCEPTION_RECORD *exception_record,
|
||||
struct DEstablisherFrame *frame,
|
||||
CONTEXT context,
|
||||
void *dispatcher_context)
|
||||
{
|
||||
struct DHandlerTable *handler_table;
|
||||
|
||||
__asm { mov handler_table,EAX }
|
||||
|
||||
if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
|
||||
{
|
||||
// Call all the finally blocks in this frame
|
||||
_d_local_unwind(handler_table, frame, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Jump to catch block if matching one is found
|
||||
|
||||
int ndx,prev_ndx,i;
|
||||
struct DHandlerInfo *phi;
|
||||
struct DCatchInfo *pci;
|
||||
struct DCatchBlock *pcb;
|
||||
unsigned ncatches; // number of catches in the current handler
|
||||
Object *pti;
|
||||
ClassInfo *ci;
|
||||
|
||||
ci = NULL; // only compute it if we need it
|
||||
|
||||
// walk through handler table, checking each handler
|
||||
// with an index smaller than the current table_index
|
||||
for (ndx = frame->table_index; ndx != -1; ndx = prev_ndx)
|
||||
{
|
||||
phi = &handler_table->handler_info[ndx];
|
||||
prev_ndx = phi->prev_index;
|
||||
if (phi->cioffset)
|
||||
{
|
||||
// this is a catch handler (no finally)
|
||||
pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
|
||||
ncatches = pci->ncatches;
|
||||
for (i = 0; i < ncatches; i++)
|
||||
{
|
||||
pcb = &pci->catch_block[i];
|
||||
|
||||
if (!ci)
|
||||
{
|
||||
// This code must match the translation code
|
||||
if (exception_record->ExceptionCode == STATUS_DIGITAL_MARS_D_EXCEPTION)
|
||||
{
|
||||
//printf("ei[0] = %p\n", exception_record->ExceptionInformation[0]);
|
||||
ci = **(ClassInfo ***)(exception_record->ExceptionInformation[0]);
|
||||
}
|
||||
else
|
||||
ci = &_Class_9Throwable;
|
||||
}
|
||||
|
||||
if (_d_isbaseof(ci, pcb->type))
|
||||
{
|
||||
// Matched the catch type, so we've found the handler.
|
||||
int regebp;
|
||||
|
||||
pti = _d_translate_se_to_d_exception(exception_record);
|
||||
|
||||
// Initialize catch variable
|
||||
regebp = (int)&frame->ebp; // EBP for this frame
|
||||
*(void **)(regebp + (pcb->bpoffset)) = pti;
|
||||
|
||||
// Have system call all finally blocks in intervening frames
|
||||
_global_unwind(frame, exception_record);
|
||||
|
||||
// Call all the finally blocks skipped in this frame
|
||||
_d_local_unwind(handler_table, frame, ndx);
|
||||
|
||||
frame->table_index = prev_ndx; // we are out of this handler
|
||||
|
||||
// Jump to catch block. Does not return.
|
||||
{
|
||||
unsigned catch_esp;
|
||||
fp_t catch_addr;
|
||||
|
||||
catch_addr = (fp_t)(pcb->code);
|
||||
catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
|
||||
_asm
|
||||
{
|
||||
mov EAX,catch_esp
|
||||
mov ECX,catch_addr
|
||||
mov [EAX],ECX
|
||||
mov EBP,regebp
|
||||
mov ESP,EAX // reset stack
|
||||
ret // jump to catch block
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Exception filter for use in __try..__except block
|
||||
* surrounding call to Dmain()
|
||||
*/
|
||||
|
||||
int _d_exception_filter(struct _EXCEPTION_POINTERS *eptrs,
|
||||
int retval,
|
||||
Object **exception_object)
|
||||
{
|
||||
*exception_object = _d_translate_se_to_d_exception(eptrs->ExceptionRecord);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Throw a D object.
|
||||
*/
|
||||
|
||||
void __stdcall _d_throw(Object *h)
|
||||
{
|
||||
//printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||
//printf("\tvptr = %p\n", *(void **)h);
|
||||
RaiseException(STATUS_DIGITAL_MARS_D_EXCEPTION,
|
||||
EXCEPTION_NONCONTINUABLE,
|
||||
1, (DWORD *)&h);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Create an exception object
|
||||
*/
|
||||
|
||||
Object *_d_create_exception_object(ClassInfo *ci, char *msg)
|
||||
{
|
||||
Throwable *exc;
|
||||
|
||||
exc = (Throwable *)_d_newclass(ci);
|
||||
// BUG: what if _d_newclass() throws an out of memory exception?
|
||||
|
||||
if (msg)
|
||||
{
|
||||
exc->msglen = strlen(msg);
|
||||
exc->msg = msg;
|
||||
}
|
||||
return (Object *)exc;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Converts a Windows Structured Exception code to a D Exception Object.
|
||||
*/
|
||||
|
||||
Object *_d_translate_se_to_d_exception(EXCEPTION_RECORD *exception_record)
|
||||
{
|
||||
Object *pti;
|
||||
|
||||
switch (exception_record->ExceptionCode) {
|
||||
case STATUS_DIGITAL_MARS_D_EXCEPTION:
|
||||
// Generated D exception
|
||||
pti = (Object *)(exception_record->ExceptionInformation[0]);
|
||||
break;
|
||||
|
||||
case STATUS_INTEGER_DIVIDE_BY_ZERO:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Integer Divide by Zero");
|
||||
break;
|
||||
|
||||
case STATUS_FLOAT_DIVIDE_BY_ZERO:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Float Divide by Zero");
|
||||
break;
|
||||
|
||||
case STATUS_ACCESS_VIOLATION:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Access Violation");
|
||||
break;
|
||||
|
||||
case STATUS_STACK_OVERFLOW:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Stack Overflow");
|
||||
break;
|
||||
|
||||
// convert all other exception codes into a Win32Exception
|
||||
default:
|
||||
pti = _d_create_exception_object(&_Class_5Error, "Win32 Exception");
|
||||
break;
|
||||
}
|
||||
|
||||
return pti;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* Call finally blocks in the current stack frame until stop_index.
|
||||
* This is roughly equivalent to _local_unwind() for C in \src\win32\ehsup.c
|
||||
*/
|
||||
|
||||
void __cdecl _d_local_unwind(struct DHandlerTable *handler_table,
|
||||
struct DEstablisherFrame *frame, int stop_index)
|
||||
{
|
||||
struct DHandlerInfo *phi;
|
||||
struct DCatchInfo *pci;
|
||||
int i;
|
||||
|
||||
// Set up a special exception handler to catch double-fault exceptions.
|
||||
__asm
|
||||
{
|
||||
push dword ptr -1
|
||||
push dword ptr 0
|
||||
push offset _local_except_handler // defined in src\win32\ehsup.c
|
||||
push dword ptr fs:_except_list
|
||||
mov FS:_except_list,ESP
|
||||
}
|
||||
|
||||
for (i = frame->table_index; i != -1 && i != stop_index; i = phi->prev_index)
|
||||
{
|
||||
phi = &handler_table->handler_info[i];
|
||||
if (phi->finally_code)
|
||||
{
|
||||
// Note that it is unnecessary to adjust the ESP, as the finally block
|
||||
// accesses all items on the stack as relative to EBP.
|
||||
|
||||
DWORD *catch_ebp = &frame->ebp;
|
||||
void *blockaddr = phi->finally_code;
|
||||
|
||||
_asm
|
||||
{
|
||||
push EBX
|
||||
mov EBX,blockaddr
|
||||
push EBP
|
||||
mov EBP,catch_ebp
|
||||
call EBX
|
||||
pop EBP
|
||||
pop EBX
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_asm
|
||||
{
|
||||
pop FS:_except_list
|
||||
add ESP,12
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* external version of the unwinder
|
||||
*/
|
||||
|
||||
__declspec(naked) void __cdecl _d_local_unwind2()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
jmp _d_local_unwind
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* The frame handler, this is called for each frame that has been registered
|
||||
* in the OS except_list.
|
||||
* Input:
|
||||
* EAX the handler table for the frame
|
||||
*/
|
||||
|
||||
EXCEPTION_DISPOSITION _d_monitor_handler(
|
||||
EXCEPTION_RECORD *exception_record,
|
||||
struct DEstablisherFrame *frame,
|
||||
CONTEXT context,
|
||||
void *dispatcher_context)
|
||||
{
|
||||
if (exception_record->ExceptionFlags & EXCEPTION_UNWIND)
|
||||
{
|
||||
_d_monitorexit((Object *)frame->table_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
return ExceptionContinueSearch;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*/
|
||||
|
||||
void _d_monitor_prolog(void *x, void *y, Object *h)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push EAX
|
||||
}
|
||||
//printf("_d_monitor_prolog(x=%p, y=%p, h=%p)\n", x, y, h);
|
||||
_d_monitorenter(h);
|
||||
__asm
|
||||
{
|
||||
pop EAX
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************
|
||||
*/
|
||||
|
||||
void _d_monitor_epilog(void *x, void *y, Object *h)
|
||||
{
|
||||
//printf("_d_monitor_epilog(x=%p, y=%p, h=%p)\n", x, y, h);
|
||||
__asm
|
||||
{
|
||||
push EAX
|
||||
push EDX
|
||||
}
|
||||
_d_monitorexit(h);
|
||||
__asm
|
||||
{
|
||||
pop EDX
|
||||
pop EAX
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ======================== linux =============================== */
|
||||
|
||||
#if linux
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
extern ClassInfo D6object9Throwable7__ClassZ;
|
||||
#define _Class_9Throwable D6object9Throwable7__ClassZ;
|
||||
|
||||
extern ClassInfo D6object5Error7__ClassZ;
|
||||
#define _Class_5Error D6object5Error7__ClassZ
|
||||
|
||||
typedef int (*fp_t)(); // function pointer in ambient memory model
|
||||
|
||||
struct DHandlerInfo
|
||||
{
|
||||
unsigned offset; // offset from function address to start of guarded section
|
||||
int prev_index; // previous table index
|
||||
unsigned cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch)
|
||||
void *finally_code; // pointer to finally code to execute
|
||||
// (!=0 if try-finally)
|
||||
};
|
||||
|
||||
// Address of DHandlerTable, searched for by eh_finddata()
|
||||
|
||||
struct DHandlerTable
|
||||
{
|
||||
void *fptr; // pointer to start of function
|
||||
unsigned espoffset; // offset of ESP from EBP
|
||||
unsigned retoffset; // offset from start of function to return code
|
||||
unsigned nhandlers; // dimension of handler_info[]
|
||||
struct DHandlerInfo handler_info[1];
|
||||
};
|
||||
|
||||
struct DCatchBlock
|
||||
{
|
||||
ClassInfo *type; // catch type
|
||||
unsigned bpoffset; // EBP offset of catch var
|
||||
void *code; // catch handler code
|
||||
};
|
||||
|
||||
// Create one of these for each try-catch
|
||||
struct DCatchInfo
|
||||
{
|
||||
unsigned ncatches; // number of catch blocks
|
||||
struct DCatchBlock catch_block[1]; // data for each catch block
|
||||
};
|
||||
|
||||
// One of these is generated for each function with try-catch or try-finally
|
||||
|
||||
struct FuncTable
|
||||
{
|
||||
void *fptr; // pointer to start of function
|
||||
struct DHandlerTable *handlertable; // eh data for this function
|
||||
unsigned size; // size of function in bytes
|
||||
};
|
||||
|
||||
extern struct FuncTable *table_start;
|
||||
extern struct FuncTable *table_end;
|
||||
|
||||
void terminate()
|
||||
{
|
||||
// _asm
|
||||
// {
|
||||
// hlt
|
||||
// }
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Given address that is inside a function,
|
||||
* figure out which function it is in.
|
||||
* Return DHandlerTable if there is one, NULL if not.
|
||||
*/
|
||||
|
||||
struct DHandlerTable *__eh_finddata(void *address)
|
||||
{
|
||||
struct FuncTable *ft;
|
||||
|
||||
for (ft = (struct FuncTable *)table_start;
|
||||
ft < (struct FuncTable *)table_end;
|
||||
ft++)
|
||||
{
|
||||
if (ft->fptr <= address &&
|
||||
address < (void *)((char *)ft->fptr + ft->size))
|
||||
{
|
||||
return ft->handlertable;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
* Given EBP, find return address to caller, and caller's EBP.
|
||||
* Input:
|
||||
* regbp Value of EBP for current function
|
||||
* *pretaddr Return address
|
||||
* Output:
|
||||
* *pretaddr return address to caller
|
||||
* Returns:
|
||||
* caller's EBP
|
||||
*/
|
||||
|
||||
unsigned __eh_find_caller(unsigned regbp, unsigned *pretaddr)
|
||||
{
|
||||
unsigned bp = *(unsigned *)regbp;
|
||||
|
||||
if (bp) // if not end of call chain
|
||||
{
|
||||
// Perform sanity checks on new EBP.
|
||||
// If it is screwed up, terminate() hopefully before we do more damage.
|
||||
if (bp <= regbp)
|
||||
// stack should grow to smaller values
|
||||
terminate();
|
||||
|
||||
*pretaddr = *(unsigned *)(regbp + sizeof(int));
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Throw a D object.
|
||||
*/
|
||||
|
||||
void __stdcall _d_throw(Object *h)
|
||||
{
|
||||
unsigned regebp;
|
||||
|
||||
//printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||
//printf("\tvptr = %p\n", *(void **)h);
|
||||
|
||||
regebp = _EBP;
|
||||
|
||||
while (1) // for each function on the stack
|
||||
{
|
||||
struct DHandlerTable *handler_table;
|
||||
struct FuncTable *pfunc;
|
||||
struct DHandlerInfo *phi;
|
||||
unsigned retaddr;
|
||||
unsigned funcoffset;
|
||||
unsigned spoff;
|
||||
unsigned retoffset;
|
||||
int index;
|
||||
int dim;
|
||||
int ndx;
|
||||
int prev_ndx;
|
||||
|
||||
regebp = __eh_find_caller(regebp,&retaddr);
|
||||
if (!regebp)
|
||||
// if end of call chain
|
||||
break;
|
||||
|
||||
handler_table = __eh_finddata((void *)retaddr); // find static data associated with function
|
||||
if (!handler_table) // if no static data
|
||||
{
|
||||
continue;
|
||||
}
|
||||
funcoffset = (unsigned)handler_table->fptr;
|
||||
spoff = handler_table->espoffset;
|
||||
retoffset = handler_table->retoffset;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("retaddr = x%x\n",(unsigned)retaddr);
|
||||
printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
|
||||
regebp,funcoffset,spoff,retoffset);
|
||||
#endif
|
||||
|
||||
// Find start index for retaddr in static data
|
||||
dim = handler_table->nhandlers;
|
||||
index = -1;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
phi = &handler_table->handler_info[i];
|
||||
|
||||
if ((unsigned)retaddr >= funcoffset + phi->offset)
|
||||
index = i;
|
||||
}
|
||||
|
||||
// walk through handler table, checking each handler
|
||||
// with an index smaller than the current table_index
|
||||
for (ndx = index; ndx != -1; ndx = prev_ndx)
|
||||
{
|
||||
phi = &handler_table->handler_info[ndx];
|
||||
prev_ndx = phi->prev_index;
|
||||
if (phi->cioffset)
|
||||
{
|
||||
// this is a catch handler (no finally)
|
||||
struct DCatchInfo *pci;
|
||||
int ncatches;
|
||||
int i;
|
||||
|
||||
pci = (struct DCatchInfo *)((char *)handler_table + phi->cioffset);
|
||||
ncatches = pci->ncatches;
|
||||
for (i = 0; i < ncatches; i++)
|
||||
{
|
||||
struct DCatchBlock *pcb;
|
||||
ClassInfo *ci = **(ClassInfo ***)h;
|
||||
|
||||
pcb = &pci->catch_block[i];
|
||||
|
||||
if (_d_isbaseof(ci, pcb->type))
|
||||
{ // Matched the catch type, so we've found the handler.
|
||||
|
||||
// Initialize catch variable
|
||||
*(void **)(regebp + (pcb->bpoffset)) = h;
|
||||
|
||||
// Jump to catch block. Does not return.
|
||||
{
|
||||
unsigned catch_esp;
|
||||
fp_t catch_addr;
|
||||
|
||||
catch_addr = (fp_t)(pcb->code);
|
||||
catch_esp = regebp - handler_table->espoffset - sizeof(fp_t);
|
||||
_asm
|
||||
{
|
||||
mov EAX,catch_esp
|
||||
mov ECX,catch_addr
|
||||
mov [EAX],ECX
|
||||
mov EBP,regebp
|
||||
mov ESP,EAX // reset stack
|
||||
ret // jump to catch block
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (phi->finally_code)
|
||||
{ // Call finally block
|
||||
// Note that it is unnecessary to adjust the ESP, as the finally block
|
||||
// accesses all items on the stack as relative to EBP.
|
||||
|
||||
void *blockaddr = phi->finally_code;
|
||||
|
||||
_asm
|
||||
{
|
||||
push EBX
|
||||
mov EBX,blockaddr
|
||||
push EBP
|
||||
mov EBP,regebp
|
||||
call EBX
|
||||
pop EBP
|
||||
pop EBX
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
308
druntime/src/compiler/dmd/deh2.d
Normal file
308
druntime/src/compiler/dmd/deh2.d
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (C) 1999-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.deh2;
|
||||
|
||||
// Exception handling support for linux
|
||||
|
||||
//debug=1;
|
||||
|
||||
extern (C)
|
||||
{
|
||||
extern void* _deh_beg;
|
||||
extern void* _deh_end;
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c);
|
||||
}
|
||||
|
||||
alias int (*fp_t)(); // function pointer in ambient memory model
|
||||
|
||||
struct DHandlerInfo
|
||||
{
|
||||
uint offset; // offset from function address to start of guarded section
|
||||
uint endoffset; // offset of end of guarded section
|
||||
int prev_index; // previous table index
|
||||
uint cioffset; // offset to DCatchInfo data from start of table (!=0 if try-catch)
|
||||
void *finally_code; // pointer to finally code to execute
|
||||
// (!=0 if try-finally)
|
||||
}
|
||||
|
||||
// Address of DHandlerTable, searched for by eh_finddata()
|
||||
|
||||
struct DHandlerTable
|
||||
{
|
||||
void *fptr; // pointer to start of function
|
||||
uint espoffset; // offset of ESP from EBP
|
||||
uint retoffset; // offset from start of function to return code
|
||||
uint nhandlers; // dimension of handler_info[]
|
||||
DHandlerInfo handler_info[1];
|
||||
}
|
||||
|
||||
struct DCatchBlock
|
||||
{
|
||||
ClassInfo type; // catch type
|
||||
uint bpoffset; // EBP offset of catch var
|
||||
void *code; // catch handler code
|
||||
}
|
||||
|
||||
// Create one of these for each try-catch
|
||||
struct DCatchInfo
|
||||
{
|
||||
uint ncatches; // number of catch blocks
|
||||
DCatchBlock catch_block[1]; // data for each catch block
|
||||
}
|
||||
|
||||
// One of these is generated for each function with try-catch or try-finally
|
||||
|
||||
struct FuncTable
|
||||
{
|
||||
void *fptr; // pointer to start of function
|
||||
DHandlerTable *handlertable; // eh data for this function
|
||||
uint fsize; // size of function in bytes
|
||||
}
|
||||
|
||||
void terminate()
|
||||
{
|
||||
asm
|
||||
{
|
||||
hlt ;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Given address that is inside a function,
|
||||
* figure out which function it is in.
|
||||
* Return DHandlerTable if there is one, NULL if not.
|
||||
*/
|
||||
|
||||
DHandlerTable *__eh_finddata(void *address)
|
||||
{
|
||||
FuncTable *ft;
|
||||
|
||||
// debug printf("__eh_finddata(address = x%x)\n", address);
|
||||
// debug printf("_deh_beg = x%x, _deh_end = x%x\n", &_deh_beg, &_deh_end);
|
||||
for (ft = cast(FuncTable *)&_deh_beg;
|
||||
ft < cast(FuncTable *)&_deh_end;
|
||||
ft++)
|
||||
{
|
||||
// debug printf("\tfptr = x%x, fsize = x%03x, handlertable = x%x\n",
|
||||
// ft.fptr, ft.fsize, ft.handlertable);
|
||||
|
||||
if (ft.fptr <= address &&
|
||||
address < cast(void *)(cast(char *)ft.fptr + ft.fsize))
|
||||
{
|
||||
// debug printf("\tfound handler table\n");
|
||||
return ft.handlertable;
|
||||
}
|
||||
}
|
||||
// debug printf("\tnot found\n");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
* Given EBP, find return address to caller, and caller's EBP.
|
||||
* Input:
|
||||
* regbp Value of EBP for current function
|
||||
* *pretaddr Return address
|
||||
* Output:
|
||||
* *pretaddr return address to caller
|
||||
* Returns:
|
||||
* caller's EBP
|
||||
*/
|
||||
|
||||
uint __eh_find_caller(uint regbp, uint *pretaddr)
|
||||
{
|
||||
uint bp = *cast(uint *)regbp;
|
||||
|
||||
if (bp) // if not end of call chain
|
||||
{
|
||||
// Perform sanity checks on new EBP.
|
||||
// If it is screwed up, terminate() hopefully before we do more damage.
|
||||
if (bp <= regbp)
|
||||
// stack should grow to smaller values
|
||||
terminate();
|
||||
|
||||
*pretaddr = *cast(uint *)(regbp + int.sizeof);
|
||||
}
|
||||
return bp;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Throw a D object.
|
||||
*/
|
||||
|
||||
extern (Windows) void _d_throw(Object *h)
|
||||
{
|
||||
uint regebp;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("_d_throw(h = %p, &h = %p)\n", h, &h);
|
||||
printf("\tvptr = %p\n", *cast(void **)h);
|
||||
}
|
||||
|
||||
asm
|
||||
{
|
||||
mov regebp,EBP ;
|
||||
}
|
||||
|
||||
//static uint abc;
|
||||
//if (++abc == 2) *(char *)0=0;
|
||||
|
||||
//int count = 0;
|
||||
while (1) // for each function on the stack
|
||||
{
|
||||
DHandlerTable *handler_table;
|
||||
FuncTable *pfunc;
|
||||
DHandlerInfo *phi;
|
||||
uint retaddr;
|
||||
uint funcoffset;
|
||||
uint spoff;
|
||||
uint retoffset;
|
||||
int index;
|
||||
int dim;
|
||||
int ndx;
|
||||
int prev_ndx;
|
||||
|
||||
regebp = __eh_find_caller(regebp,&retaddr);
|
||||
if (!regebp)
|
||||
{ // if end of call chain
|
||||
debug printf("end of call chain\n");
|
||||
break;
|
||||
}
|
||||
|
||||
debug printf("found caller, EBP = x%x, retaddr = x%x\n", regebp, retaddr);
|
||||
//if (++count == 12) *(char*)0=0;
|
||||
handler_table = __eh_finddata(cast(void *)retaddr); // find static data associated with function
|
||||
if (!handler_table) // if no static data
|
||||
{
|
||||
debug printf("no handler table\n");
|
||||
continue;
|
||||
}
|
||||
funcoffset = cast(uint)handler_table.fptr;
|
||||
spoff = handler_table.espoffset;
|
||||
retoffset = handler_table.retoffset;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("retaddr = x%x\n",cast(uint)retaddr);
|
||||
printf("regebp=x%04x, funcoffset=x%04x, spoff=x%x, retoffset=x%x\n",
|
||||
regebp,funcoffset,spoff,retoffset);
|
||||
}
|
||||
|
||||
// Find start index for retaddr in static data
|
||||
dim = handler_table.nhandlers;
|
||||
|
||||
debug
|
||||
{
|
||||
printf("handler_info[]:\n");
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
phi = &handler_table.handler_info[i];
|
||||
printf("\t[%d]: offset = x%04x, endoffset = x%04x, prev_index = %d, cioffset = x%04x, finally_code = %x\n",
|
||||
i, phi.offset, phi.endoffset, phi.prev_index, phi.cioffset, phi.finally_code);
|
||||
}
|
||||
}
|
||||
|
||||
index = -1;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
phi = &handler_table.handler_info[i];
|
||||
|
||||
debug printf("i = %d, phi.offset = %04x\n", i, funcoffset + phi.offset);
|
||||
if (cast(uint)retaddr > funcoffset + phi.offset &&
|
||||
cast(uint)retaddr <= funcoffset + phi.endoffset)
|
||||
index = i;
|
||||
}
|
||||
debug printf("index = %d\n", index);
|
||||
|
||||
// walk through handler table, checking each handler
|
||||
// with an index smaller than the current table_index
|
||||
for (ndx = index; ndx != -1; ndx = prev_ndx)
|
||||
{
|
||||
phi = &handler_table.handler_info[ndx];
|
||||
prev_ndx = phi.prev_index;
|
||||
if (phi.cioffset)
|
||||
{
|
||||
// this is a catch handler (no finally)
|
||||
DCatchInfo *pci;
|
||||
int ncatches;
|
||||
int i;
|
||||
|
||||
pci = cast(DCatchInfo *)(cast(char *)handler_table + phi.cioffset);
|
||||
ncatches = pci.ncatches;
|
||||
for (i = 0; i < ncatches; i++)
|
||||
{
|
||||
DCatchBlock *pcb;
|
||||
ClassInfo ci = **cast(ClassInfo **)h;
|
||||
|
||||
pcb = &pci.catch_block[i];
|
||||
|
||||
if (_d_isbaseof(ci, pcb.type))
|
||||
{ // Matched the catch type, so we've found the handler.
|
||||
|
||||
// Initialize catch variable
|
||||
*cast(void **)(regebp + (pcb.bpoffset)) = h;
|
||||
|
||||
// Jump to catch block. Does not return.
|
||||
{
|
||||
uint catch_esp;
|
||||
fp_t catch_addr;
|
||||
|
||||
catch_addr = cast(fp_t)(pcb.code);
|
||||
catch_esp = regebp - handler_table.espoffset - fp_t.sizeof;
|
||||
asm
|
||||
{
|
||||
mov EAX,catch_esp ;
|
||||
mov ECX,catch_addr ;
|
||||
mov [EAX],ECX ;
|
||||
mov EBP,regebp ;
|
||||
mov ESP,EAX ; // reset stack
|
||||
ret ; // jump to catch block
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (phi.finally_code)
|
||||
{ // Call finally block
|
||||
// Note that it is unnecessary to adjust the ESP, as the finally block
|
||||
// accesses all items on the stack as relative to EBP.
|
||||
|
||||
void *blockaddr = phi.finally_code;
|
||||
|
||||
asm
|
||||
{
|
||||
push EBX ;
|
||||
mov EBX,blockaddr ;
|
||||
push EBP ;
|
||||
mov EBP,regebp ;
|
||||
call EBX ;
|
||||
pop EBP ;
|
||||
pop EBX ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
315
druntime/src/compiler/dmd/dmain2.d
Normal file
315
druntime/src/compiler/dmd/dmain2.d
Normal file
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Placed into the Public Domain.
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.dmain2;
|
||||
|
||||
private
|
||||
{
|
||||
import util.console;
|
||||
import stdc.stddef;
|
||||
import stdc.stdlib;
|
||||
import stdc.string;
|
||||
}
|
||||
|
||||
version(Windows)
|
||||
{
|
||||
extern (Windows) void* LocalFree(void*);
|
||||
extern (Windows) wchar_t* GetCommandLineW();
|
||||
extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*);
|
||||
extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
|
||||
pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
|
||||
}
|
||||
|
||||
extern (C) void _STI_monitor_staticctor();
|
||||
extern (C) void _STD_monitor_staticdtor();
|
||||
extern (C) void _STI_critical_init();
|
||||
extern (C) void _STD_critical_term();
|
||||
extern (C) void gc_init();
|
||||
extern (C) void gc_term();
|
||||
extern (C) void _minit();
|
||||
extern (C) void _moduleCtor();
|
||||
extern (C) void _moduleDtor();
|
||||
extern (C) void thread_joinAll();
|
||||
|
||||
/***********************************
|
||||
* These functions must be defined for any D program linked
|
||||
* against this library.
|
||||
*/
|
||||
extern (C) void onAssertError(string file, size_t line);
|
||||
extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
|
||||
extern (C) void onArrayBoundsError(string file, size_t line);
|
||||
extern (C) void onHiddenFuncError(Object o);
|
||||
extern (C) void onSwitchError(string file, size_t line);
|
||||
extern (C) bool runModuleUnitTests();
|
||||
|
||||
// this function is called from the utf module
|
||||
//extern (C) void onUnicodeError(string msg, size_t idx);
|
||||
|
||||
/***********************************
|
||||
* These are internal callbacks for various language errors.
|
||||
*/
|
||||
extern (C) void _d_assert(string file, uint line)
|
||||
{
|
||||
onAssertError(file, line);
|
||||
}
|
||||
|
||||
extern (C) static void _d_assert_msg(string msg, string file, uint line)
|
||||
{
|
||||
onAssertErrorMsg(file, line, msg);
|
||||
}
|
||||
|
||||
extern (C) void _d_array_bounds(string file, uint line)
|
||||
{
|
||||
onArrayBoundsError(file, line);
|
||||
}
|
||||
|
||||
extern (C) void _d_switch_error(string file, uint line)
|
||||
{
|
||||
onSwitchError(file, line);
|
||||
}
|
||||
|
||||
extern (C) void _d_hidden_func()
|
||||
{
|
||||
Object o;
|
||||
asm
|
||||
{
|
||||
mov o, EAX;
|
||||
}
|
||||
onHiddenFuncError(o);
|
||||
}
|
||||
|
||||
bool _d_isHalting = false;
|
||||
|
||||
extern (C) bool rt_isHalting()
|
||||
{
|
||||
return _d_isHalting;
|
||||
}
|
||||
|
||||
extern (C) bool rt_trapExceptions = true;
|
||||
|
||||
void _d_criticalInit()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
}
|
||||
|
||||
alias void delegate(Throwable) ExceptionHandler;
|
||||
|
||||
extern (C) bool rt_init(ExceptionHandler dg = null)
|
||||
{
|
||||
_d_criticalInit();
|
||||
|
||||
try
|
||||
{
|
||||
gc_init();
|
||||
version (Windows)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
if (dg)
|
||||
dg(e);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
_d_criticalTerm();
|
||||
return false;
|
||||
}
|
||||
|
||||
void _d_criticalTerm()
|
||||
{
|
||||
version (linux)
|
||||
{
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
}
|
||||
|
||||
extern (C) bool rt_term(ExceptionHandler dg = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
return true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
if (dg)
|
||||
dg(e);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
_d_criticalTerm();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* The D main() function supplied by the user's program
|
||||
*/
|
||||
int main(char[][] args);
|
||||
|
||||
/***********************************
|
||||
* Substitutes for the C main() function.
|
||||
* It's purpose is to wrap the call to the D main()
|
||||
* function and catch any unhandled exceptions.
|
||||
*/
|
||||
|
||||
extern (C) int main(int argc, char **argv)
|
||||
{
|
||||
char[][] args;
|
||||
int result;
|
||||
|
||||
version (linux)
|
||||
{
|
||||
_STI_monitor_staticctor();
|
||||
_STI_critical_init();
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
wchar_t* wcbuf = GetCommandLineW();
|
||||
size_t wclen = wcslen(wcbuf);
|
||||
int wargc = 0;
|
||||
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
|
||||
assert(wargc == argc);
|
||||
|
||||
char* cargp = null;
|
||||
size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
|
||||
|
||||
cargp = cast(char*) alloca(cargl);
|
||||
args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
|
||||
|
||||
for (size_t i = 0, p = 0; i < wargc; i++)
|
||||
{
|
||||
int wlen = wcslen(wargs[i]);
|
||||
int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
|
||||
args[i] = cargp[p .. p+clen];
|
||||
p += clen; assert(p <= cargl);
|
||||
WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
|
||||
}
|
||||
LocalFree(wargs);
|
||||
wargs = null;
|
||||
wargc = 0;
|
||||
}
|
||||
else version (linux)
|
||||
{
|
||||
char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
|
||||
scope(exit) free(am);
|
||||
|
||||
for (size_t i = 0; i < argc; i++)
|
||||
{
|
||||
auto len = strlen(argv[i]);
|
||||
am[i] = argv[i][0 .. len];
|
||||
}
|
||||
args = am[0 .. argc];
|
||||
}
|
||||
|
||||
bool trapExceptions = rt_trapExceptions;
|
||||
|
||||
void tryExec(void delegate() dg)
|
||||
{
|
||||
|
||||
if (trapExceptions)
|
||||
{
|
||||
try
|
||||
{
|
||||
dg();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
while (e)
|
||||
{
|
||||
if (e.file)
|
||||
{
|
||||
// fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
|
||||
console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", e.toString());
|
||||
console (e.toString)("\n");
|
||||
}
|
||||
if (e.info)
|
||||
{
|
||||
console ("----------------\n");
|
||||
foreach (t; e.info)
|
||||
console (t)("\n");
|
||||
}
|
||||
if (e.next)
|
||||
console ("\n");
|
||||
e = e.next;
|
||||
}
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
// fprintf(stderr, "%.*s\n", o.toString());
|
||||
console (o.toString)("\n");
|
||||
result = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dg();
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: The lifetime of a process is much like the lifetime of an object:
|
||||
// it is initialized, then used, then destroyed. If initialization
|
||||
// fails, the successive two steps are never reached. However, if
|
||||
// initialization succeeds, then cleanup will occur even if the use
|
||||
// step fails in some way. Here, the use phase consists of running
|
||||
// the user's main function. If main terminates with an exception,
|
||||
// the exception is handled and then cleanup begins. An exception
|
||||
// thrown during cleanup, however, will abort the cleanup process.
|
||||
|
||||
void runMain()
|
||||
{
|
||||
result = main(args);
|
||||
}
|
||||
|
||||
void runAll()
|
||||
{
|
||||
gc_init();
|
||||
version (Windows)
|
||||
_minit();
|
||||
_moduleCtor();
|
||||
if (runModuleUnitTests())
|
||||
tryExec(&runMain);
|
||||
thread_joinAll();
|
||||
_d_isHalting = true;
|
||||
_moduleDtor();
|
||||
gc_term();
|
||||
}
|
||||
|
||||
tryExec(&runAll);
|
||||
|
||||
version (linux)
|
||||
{
|
||||
_STD_critical_term();
|
||||
_STD_monitor_staticdtor();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
24
druntime/src/compiler/dmd/invariant.d
Normal file
24
druntime/src/compiler/dmd/invariant.d
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
void _d_invariant(Object o)
|
||||
{ ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
do
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
}
|
||||
25
druntime/src/compiler/dmd/invariant_.d
Normal file
25
druntime/src/compiler/dmd/invariant_.d
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
module rt.invariant_;
|
||||
|
||||
extern (C) void _d_invariant(Object o)
|
||||
{ ClassInfo c;
|
||||
|
||||
//printf("__d_invariant(%p)\n", o);
|
||||
|
||||
// BUG: needs to be filename/line of caller, not library routine
|
||||
assert(o !is null); // just do null check, not invariant check
|
||||
|
||||
c = o.classinfo;
|
||||
do
|
||||
{
|
||||
if (c.classInvariant)
|
||||
{
|
||||
(*c.classInvariant)(o);
|
||||
}
|
||||
c = c.base;
|
||||
} while (c);
|
||||
}
|
||||
1081
druntime/src/compiler/dmd/lifetime.d
Normal file
1081
druntime/src/compiler/dmd/lifetime.d
Normal file
File diff suppressed because it is too large
Load Diff
295
druntime/src/compiler/dmd/llmath.d
Normal file
295
druntime/src/compiler/dmd/llmath.d
Normal file
@@ -0,0 +1,295 @@
|
||||
// llmath.d
|
||||
// Copyright (C) 1993-2003 by Digital Mars, www.digitalmars.com
|
||||
// All Rights Reserved
|
||||
// Written by Walter Bright
|
||||
|
||||
module rt.llmath;
|
||||
|
||||
// Compiler runtime support for 64 bit longs
|
||||
|
||||
extern (C):
|
||||
|
||||
|
||||
/***************************************
|
||||
* Unsigned long divide.
|
||||
* Input:
|
||||
* [EDX,EAX],[ECX,EBX]
|
||||
* Output:
|
||||
* [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
|
||||
* [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
|
||||
* ESI,EDI destroyed
|
||||
*/
|
||||
|
||||
void __ULDIV__()
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked ;
|
||||
test ECX,ECX ;
|
||||
jz uldiv ;
|
||||
|
||||
push EBP ;
|
||||
|
||||
// left justify [ECX,EBX] and leave count of shifts + 1 in EBP
|
||||
|
||||
mov EBP,1 ; // at least 1 shift
|
||||
test ECX,ECX ; // left justified?
|
||||
js L1 ; // yes
|
||||
jnz L2 ;
|
||||
add EBP,8 ;
|
||||
mov CH,CL ;
|
||||
mov CL,BH ;
|
||||
mov BH,BL ;
|
||||
xor BL,BL ; // [ECX,EBX] <<= 8
|
||||
test ECX,ECX ;
|
||||
js L1 ;
|
||||
even ;
|
||||
L2: inc EBP ; // another shift
|
||||
shl EBX,1 ;
|
||||
rcl ECX,1 ; // [ECX,EBX] <<= 1
|
||||
jno L2 ; // not left justified yet
|
||||
|
||||
L1: mov ESI,ECX ;
|
||||
mov EDI,EBX ; // [ESI,EDI] = divisor
|
||||
|
||||
mov ECX,EDX ;
|
||||
mov EBX,EAX ; // [ECX,EBX] = [EDX,EAX]
|
||||
xor EAX,EAX ;
|
||||
cdq ; // [EDX,EAX] = 0
|
||||
even ;
|
||||
L4: cmp ESI,ECX ; // is [ECX,EBX] > [ESI,EDI]?
|
||||
ja L3 ; // yes
|
||||
jb L5 ; // definitely less than
|
||||
cmp EDI,EBX ; // check low order word
|
||||
ja L3 ;
|
||||
L5: sub EBX,EDI ;
|
||||
sbb ECX,ESI ; // [ECX,EBX] -= [ESI,EDI]
|
||||
stc ; // rotate in a 1
|
||||
L3: rcl EAX,1 ;
|
||||
rcl EDX,1 ; // [EDX,EAX] = ([EDX,EAX] << 1) + C
|
||||
shr ESI,1 ;
|
||||
rcr EDI,1 ; // [ESI,EDI] >>= 1
|
||||
dec EBP ; // control count
|
||||
jne L4 ;
|
||||
pop EBP ;
|
||||
ret ;
|
||||
|
||||
div0: mov EAX,-1 ;
|
||||
cwd ; // quotient is -1
|
||||
// xor ECX,ECX ;
|
||||
// mov EBX,ECX ; // remainder is 0 (ECX and EBX already 0)
|
||||
pop EBP ;
|
||||
ret ;
|
||||
|
||||
uldiv: test EDX,EDX ;
|
||||
jnz D3 ;
|
||||
// Both high words are 0, we can use the DIV instruction
|
||||
div EBX ;
|
||||
mov EBX,EDX ;
|
||||
mov EDX,ECX ; // EDX = ECX = 0
|
||||
ret ;
|
||||
|
||||
even ;
|
||||
D3: // Divide [EDX,EAX] by EBX
|
||||
mov ECX,EAX ;
|
||||
mov EAX,EDX ;
|
||||
xor EDX,EDX ;
|
||||
div EBX ;
|
||||
xchg ECX,EAX ;
|
||||
div EBX ;
|
||||
// ECX,EAX = result
|
||||
// EDX = remainder
|
||||
mov EBX,EDX ;
|
||||
mov EDX,ECX ;
|
||||
xor ECX,ECX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* Signed long divide.
|
||||
* Input:
|
||||
* [EDX,EAX],[ECX,EBX]
|
||||
* Output:
|
||||
* [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
|
||||
* [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
|
||||
* ESI,EDI destroyed
|
||||
*/
|
||||
|
||||
void __LDIV__()
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked ;
|
||||
test EDX,EDX ; // [EDX,EAX] negative?
|
||||
jns L10 ; // no
|
||||
//neg64 EDX,EAX ; // [EDX,EAX] = -[EDX,EAX]
|
||||
neg EDX ;
|
||||
neg EAX ;
|
||||
sbb EDX,0 ;
|
||||
test ECX,ECX ; // [ECX,EBX] negative?
|
||||
jns L11 ; // no
|
||||
//neg64 ECX,EBX ;
|
||||
neg ECX ;
|
||||
neg EBX ;
|
||||
sbb ECX,0 ;
|
||||
call __ULDIV__ ;
|
||||
//neg64 ECX,EBX ; // remainder same sign as dividend
|
||||
neg ECX ;
|
||||
neg EBX ;
|
||||
sbb ECX,0 ;
|
||||
ret ;
|
||||
|
||||
L11: call __ULDIV__ ;
|
||||
//neg64 ECX,EBX ; // remainder same sign as dividend
|
||||
neg ECX ;
|
||||
neg EBX ;
|
||||
sbb ECX,0 ;
|
||||
//neg64 EDX,EAX ; // quotient is negative
|
||||
neg EDX ;
|
||||
neg EAX ;
|
||||
sbb EDX,0 ;
|
||||
ret ;
|
||||
|
||||
L10: test ECX,ECX ; // [ECX,EBX] negative?
|
||||
jns L12 ; // no (all is positive)
|
||||
//neg64 ECX,EBX ;
|
||||
neg ECX ;
|
||||
neg EBX ;
|
||||
sbb ECX,0 ;
|
||||
call __ULDIV__ ;
|
||||
//neg64 EDX,EAX ; // quotient is negative
|
||||
neg EDX ;
|
||||
neg EAX ;
|
||||
sbb EDX,0 ;
|
||||
ret ;
|
||||
|
||||
L12: jmp __ULDIV__ ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***************************************
|
||||
* Compare [EDX,EAX] with [ECX,EBX]
|
||||
* Signed
|
||||
* Returns result in flags
|
||||
*/
|
||||
|
||||
void __LCMP__()
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked ;
|
||||
cmp EDX,ECX ;
|
||||
jne C1 ;
|
||||
push EDX ;
|
||||
xor EDX,EDX ;
|
||||
cmp EAX,EBX ;
|
||||
jz C2 ;
|
||||
ja C3 ;
|
||||
dec EDX ;
|
||||
pop EDX ;
|
||||
ret ;
|
||||
|
||||
C3: inc EDX ;
|
||||
C2: pop EDX ;
|
||||
C1: ret ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Convert ulong to real
|
||||
|
||||
private real adjust = cast(real)0x800_0000_0000_0000 * 0x10;
|
||||
|
||||
real __U64_LDBL()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
push EDX ;
|
||||
push EAX ;
|
||||
and dword ptr 4[ESP], 0x7FFFFFFF ;
|
||||
fild qword ptr [ESP] ;
|
||||
test EDX,EDX ;
|
||||
jns L1 ;
|
||||
fld real ptr adjust ;
|
||||
faddp ST(1), ST ;
|
||||
L1: ;
|
||||
add ESP, 8 ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
// Same as __U64_LDBL, but return result as double in [EDX,EAX]
|
||||
ulong __ULLNGDBL()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
call __U64_LDBL ;
|
||||
sub ESP,8 ;
|
||||
fstp double ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert double to ulong
|
||||
|
||||
private short roundTo0 = 0xFBF;
|
||||
|
||||
ulong __DBLULLNG()
|
||||
{
|
||||
// BUG: should handle NAN's and overflows
|
||||
asm
|
||||
{ naked ;
|
||||
push EDX ;
|
||||
push EAX ;
|
||||
fld double ptr [ESP] ;
|
||||
sub ESP,8 ;
|
||||
fld real ptr adjust ;
|
||||
fcomp ;
|
||||
fstsw AX ;
|
||||
fstcw 8[ESP] ;
|
||||
fldcw roundTo0 ;
|
||||
sahf ;
|
||||
jae L1 ;
|
||||
fld real ptr adjust ;
|
||||
fsubp ST(1), ST ;
|
||||
fistp qword ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
fldcw [ESP] ;
|
||||
add ESP,8 ;
|
||||
add EDX,0x8000_0000 ;
|
||||
ret ;
|
||||
L1: ;
|
||||
fistp qword ptr [ESP] ;
|
||||
pop EAX ;
|
||||
pop EDX ;
|
||||
fldcw [ESP] ;
|
||||
add ESP,8 ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert double in ST0 to uint
|
||||
|
||||
uint __DBLULNG()
|
||||
{
|
||||
// BUG: should handle NAN's and overflows
|
||||
asm
|
||||
{ naked ;
|
||||
sub ESP,16 ;
|
||||
fstcw 8[ESP] ;
|
||||
fldcw roundTo0 ;
|
||||
fistp qword ptr [ESP] ;
|
||||
fldcw 8[ESP] ;
|
||||
pop EAX ;
|
||||
add ESP,12 ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
104
druntime/src/compiler/dmd/mars.h
Normal file
104
druntime/src/compiler/dmd/mars.h
Normal file
@@ -0,0 +1,104 @@
|
||||
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ClassInfo;
|
||||
struct Vtbl;
|
||||
|
||||
typedef struct Vtbl
|
||||
{
|
||||
size_t len;
|
||||
void **vptr;
|
||||
} Vtbl;
|
||||
|
||||
typedef struct Interface
|
||||
{
|
||||
struct ClassInfo *classinfo;
|
||||
struct Vtbl vtbl;
|
||||
int offset;
|
||||
} Interface;
|
||||
|
||||
typedef struct Object
|
||||
{
|
||||
void **vptr;
|
||||
void *monitor;
|
||||
} Object;
|
||||
|
||||
typedef struct ClassInfo
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t initlen;
|
||||
void *init;
|
||||
|
||||
size_t namelen;
|
||||
char *name;
|
||||
|
||||
Vtbl vtbl;
|
||||
|
||||
size_t interfacelen;
|
||||
Interface *interfaces;
|
||||
|
||||
struct ClassInfo *baseClass;
|
||||
|
||||
void *destructor;
|
||||
void *invariant;
|
||||
|
||||
int flags;
|
||||
} ClassInfo;
|
||||
|
||||
typedef struct Throwable
|
||||
{
|
||||
Object object;
|
||||
|
||||
size_t msglen;
|
||||
char* msg;
|
||||
|
||||
size_t filelen;
|
||||
char* file;
|
||||
|
||||
size_t line;
|
||||
|
||||
struct Interface *info;
|
||||
struct Throwable *next;
|
||||
} Throwable;
|
||||
|
||||
typedef struct Array
|
||||
{
|
||||
size_t length;
|
||||
void *ptr;
|
||||
} Array;
|
||||
|
||||
typedef struct Delegate
|
||||
{
|
||||
void *thisptr;
|
||||
void (*funcptr)();
|
||||
} Delegate;
|
||||
|
||||
void _d_monitorenter(Object *h);
|
||||
void _d_monitorexit(Object *h);
|
||||
|
||||
int _d_isbaseof(ClassInfo *b, ClassInfo *c);
|
||||
Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
|
||||
|
||||
Object * _d_newclass(ClassInfo *ci);
|
||||
void _d_delclass(Object **p);
|
||||
|
||||
void _d_OutOfMemory();
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
184
druntime/src/compiler/dmd/memory.d
Normal file
184
druntime/src/compiler/dmd/memory.d
Normal file
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* This module exposes functionality for inspecting and manipulating memory.
|
||||
*
|
||||
* Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
|
||||
* All rights reserved.
|
||||
* License:
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
* Authors: Walter Bright, Sean Kelly
|
||||
*/
|
||||
module rt.memory;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version( linux )
|
||||
{
|
||||
version = SimpleLibcStackEnd;
|
||||
|
||||
version( SimpleLibcStackEnd )
|
||||
{
|
||||
extern (C) extern void* __libc_stack_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_stackBottom()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked;
|
||||
mov EAX,FS:4;
|
||||
ret;
|
||||
}
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
version( SimpleLibcStackEnd )
|
||||
{
|
||||
return __libc_stack_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
// See discussion: http://autopackage.org/forums/viewtopic.php?t=22
|
||||
static void** libc_stack_end;
|
||||
|
||||
if( libc_stack_end == libc_stack_end.init )
|
||||
{
|
||||
void* handle = dlopen( null, RTLD_NOW );
|
||||
libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
|
||||
dlclose( handle );
|
||||
}
|
||||
return *libc_stack_end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_stackTop()
|
||||
{
|
||||
version( D_InlineAsm_X86 )
|
||||
{
|
||||
asm
|
||||
{
|
||||
naked;
|
||||
mov EAX, ESP;
|
||||
ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Architecture not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
extern int _xi_a; // &_xi_a just happens to be start of data segment
|
||||
extern int _edata; // &_edata is start of BSS segment
|
||||
extern int _end; // &_end is past end of BSS
|
||||
}
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
extern (C)
|
||||
{
|
||||
extern int _data;
|
||||
extern int __data_start;
|
||||
extern int _end;
|
||||
extern int _data_start__;
|
||||
extern int _data_end__;
|
||||
extern int _bss_start__;
|
||||
extern int _bss_end__;
|
||||
extern int __fini_array_end;
|
||||
}
|
||||
|
||||
alias __data_start Data_Start;
|
||||
alias _end Data_End;
|
||||
}
|
||||
|
||||
alias void delegate( void*, void* ) scanFn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void rt_scanStaticData( scanFn scan )
|
||||
{
|
||||
scan(rt_staticDataBottom(), rt_staticDataTop());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_staticDataBottom()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
return &_xi_a;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
return &__data_start;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern (C) void* rt_staticDataTop()
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
return &_end;
|
||||
}
|
||||
else version( linux )
|
||||
{
|
||||
return &_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert( false, "Operating system not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
120
druntime/src/compiler/dmd/memset.d
Normal file
120
druntime/src/compiler/dmd/memset.d
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
module rt.memset;
|
||||
|
||||
|
||||
extern (C)
|
||||
{
|
||||
// Functions from the C library.
|
||||
void *memcpy(void *, void *, size_t);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
short *_memset16(short *p, short value, size_t count)
|
||||
{
|
||||
short *pstart = p;
|
||||
short *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
int *_memset32(int *p, int value, size_t count)
|
||||
{
|
||||
version (X86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
mov EDI,p ;
|
||||
mov EAX,value ;
|
||||
mov ECX,count ;
|
||||
mov EDX,EDI ;
|
||||
rep ;
|
||||
stosd ;
|
||||
mov EAX,EDX ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int *pstart = p;
|
||||
int *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
}
|
||||
|
||||
long *_memset64(long *p, long value, size_t count)
|
||||
{
|
||||
long *pstart = p;
|
||||
long *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
cdouble *_memset128(cdouble *p, cdouble value, size_t count)
|
||||
{
|
||||
cdouble *pstart = p;
|
||||
cdouble *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
real *_memset80(real *p, real value, size_t count)
|
||||
{
|
||||
real *pstart = p;
|
||||
real *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
creal *_memset160(creal *p, creal value, size_t count)
|
||||
{
|
||||
creal *pstart = p;
|
||||
creal *ptop;
|
||||
|
||||
for (ptop = &p[count]; p < ptop; p++)
|
||||
*p = value;
|
||||
return pstart;
|
||||
}
|
||||
|
||||
void *_memsetn(void *p, void *value, int count, size_t sizelem)
|
||||
{ void *pstart = p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
memcpy(p, value, sizelem);
|
||||
p = cast(void *)(cast(char *)p + sizelem);
|
||||
}
|
||||
return pstart;
|
||||
}
|
||||
79
druntime/src/compiler/dmd/minit.asm
Normal file
79
druntime/src/compiler/dmd/minit.asm
Normal file
@@ -0,0 +1,79 @@
|
||||
;_ minit.asm
|
||||
; Written by Walter Bright
|
||||
; Digital Mars
|
||||
; http://www.digitalmars.com/d/
|
||||
; Placed into the Public Domain
|
||||
|
||||
include macros.asm
|
||||
|
||||
ifdef _WIN32
|
||||
DATAGRP EQU FLAT
|
||||
else
|
||||
DATAGRP EQU DGROUP
|
||||
endif
|
||||
|
||||
; Provide a default resolution for weak extern records, no way in C
|
||||
; to define an omf symbol with a specific value
|
||||
public __nullext
|
||||
__nullext equ 0
|
||||
|
||||
extrn __moduleinfo_array:near
|
||||
|
||||
; This bit of assembler is needed because, from C or D, one cannot
|
||||
; specify the names of data segments. Why does this matter?
|
||||
; All the ModuleInfo pointers are placed into a segment named 'FM'.
|
||||
; The order in which they are placed in 'FM' is arbitrarily up to the linker.
|
||||
; In order to walk all the pointers, we need to be able to find the
|
||||
; beginning and the end of the 'FM' segment.
|
||||
; This is done by bracketing the 'FM' segment with two other, empty,
|
||||
; segments named 'FMB' and 'FME'. Since this module is the only one that
|
||||
; ever refers to 'FMB' and 'FME', we get to control the order in which
|
||||
; these segments appear relative to 'FM' by using a GROUP statement.
|
||||
; So, we have in memory:
|
||||
; FMB empty segment
|
||||
; FM contains all the pointers
|
||||
; FME empty segment
|
||||
; and finding the limits of FM is as easy as taking the address of FMB
|
||||
; and the address of FME.
|
||||
|
||||
; These segments bracket FM, which contains the list of ModuleInfo pointers
|
||||
FMB segment dword use32 public 'DATA'
|
||||
FMB ends
|
||||
FM segment dword use32 public 'DATA'
|
||||
FM ends
|
||||
FME segment dword use32 public 'DATA'
|
||||
FME ends
|
||||
|
||||
; This leaves room in the _fatexit() list for _moduleDtor()
|
||||
XOB segment dword use32 public 'BSS'
|
||||
XOB ends
|
||||
XO segment dword use32 public 'BSS'
|
||||
dd ?
|
||||
XO ends
|
||||
XOE segment dword use32 public 'BSS'
|
||||
XOE ends
|
||||
|
||||
DGROUP group FMB,FM,FME
|
||||
|
||||
begcode minit
|
||||
|
||||
; extern (C) void _minit();
|
||||
; Converts array of ModuleInfo pointers to a D dynamic array of them,
|
||||
; so they can be accessed via D.
|
||||
; Result is written to:
|
||||
; extern (C) ModuleInfo[] _moduleinfo_array;
|
||||
|
||||
public __minit
|
||||
__minit proc near
|
||||
mov EDX,offset DATAGRP:FMB
|
||||
mov EAX,offset DATAGRP:FME
|
||||
mov dword ptr __moduleinfo_array+4,EDX
|
||||
sub EAX,EDX ; size in bytes of FM segment
|
||||
shr EAX,2 ; convert to array length
|
||||
mov dword ptr __moduleinfo_array,EAX
|
||||
ret
|
||||
__minit endp
|
||||
|
||||
endcode minit
|
||||
|
||||
end
|
||||
BIN
druntime/src/compiler/dmd/minit.obj
Normal file
BIN
druntime/src/compiler/dmd/minit.obj
Normal file
Binary file not shown.
208
druntime/src/compiler/dmd/monitor.c
Normal file
208
druntime/src/compiler/dmd/monitor.c
Normal file
@@ -0,0 +1,208 @@
|
||||
// D programming language runtime library
|
||||
// Public Domain
|
||||
// written by Walter Bright, Digital Mars
|
||||
// www.digitalmars.com
|
||||
|
||||
// This is written in C because nobody has written a pthreads interface
|
||||
// to D yet.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if _WIN32
|
||||
#elif linux
|
||||
#define USE_PTHREADS 1
|
||||
#else
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "mars.h"
|
||||
|
||||
// This is what the monitor reference in Object points to
|
||||
typedef struct Monitor
|
||||
{
|
||||
void* impl; // for user-level monitors
|
||||
Array devt; // for internal monitors
|
||||
|
||||
#if _WIN32
|
||||
CRITICAL_SECTION mon;
|
||||
#endif
|
||||
|
||||
#if USE_PTHREADS
|
||||
pthread_mutex_t mon;
|
||||
#endif
|
||||
} Monitor;
|
||||
|
||||
#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon)
|
||||
|
||||
static volatile int inited;
|
||||
|
||||
/* =============================== Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
static CRITICAL_SECTION _monitor_critsec;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&_monitor_critsec);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
DeleteCriticalSection(&_monitor_critsec);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
EnterCriticalSection(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
InitializeCriticalSection(&cs->mon);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
LeaveCriticalSection(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
DeleteCriticalSection(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
EnterCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
LeaveCriticalSection(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* =============================== linux ============================ */
|
||||
|
||||
#if USE_PTHREADS
|
||||
|
||||
// Includes attribute fixes from David Friedman's GDC port
|
||||
|
||||
static pthread_mutex_t _monitor_critsec;
|
||||
static pthread_mutexattr_t _monitors_attr;
|
||||
|
||||
void _STI_monitor_staticctor()
|
||||
{
|
||||
if (!inited)
|
||||
{
|
||||
pthread_mutexattr_init(&_monitors_attr);
|
||||
pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
pthread_mutex_init(&_monitor_critsec, 0);
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_monitor_staticdtor()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
pthread_mutex_destroy(&_monitor_critsec);
|
||||
pthread_mutexattr_destroy(&_monitors_attr);
|
||||
}
|
||||
}
|
||||
|
||||
void _d_monitor_create(Object *h)
|
||||
{
|
||||
/*
|
||||
* NOTE: Assume this is only called when h->monitor is null prior to the
|
||||
* call. However, please note that another thread may call this function
|
||||
* at the same time, so we can not assert this here. Instead, try and
|
||||
* create a lock, and if one already exists then forget about it.
|
||||
*/
|
||||
|
||||
//printf("+_d_monitor_create(%p)\n", h);
|
||||
assert(h);
|
||||
Monitor *cs = NULL;
|
||||
pthread_mutex_lock(&_monitor_critsec);
|
||||
if (!h->monitor)
|
||||
{
|
||||
cs = (Monitor *)calloc(sizeof(Monitor), 1);
|
||||
assert(cs);
|
||||
pthread_mutex_init(&cs->mon, & _monitors_attr);
|
||||
h->monitor = (void *)cs;
|
||||
cs = NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&_monitor_critsec);
|
||||
if (cs)
|
||||
free(cs);
|
||||
//printf("-_d_monitor_create(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_destroy(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_destroy(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_destroy(MONPTR(h));
|
||||
free((void *)h->monitor);
|
||||
h->monitor = NULL;
|
||||
//printf("-_d_monitor_destroy(%p)\n", h);
|
||||
}
|
||||
|
||||
int _d_monitor_lock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_acquire(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_lock(MONPTR(h));
|
||||
//printf("-_d_monitor_acquire(%p)\n", h);
|
||||
}
|
||||
|
||||
void _d_monitor_unlock(Object *h)
|
||||
{
|
||||
//printf("+_d_monitor_release(%p)\n", h);
|
||||
assert(h && h->monitor && !(((Monitor*)h->monitor)->impl));
|
||||
pthread_mutex_unlock(MONPTR(h));
|
||||
//printf("-_d_monitor_release(%p)\n", h);
|
||||
}
|
||||
|
||||
#endif
|
||||
27
druntime/src/compiler/dmd/obj.d
Normal file
27
druntime/src/compiler/dmd/obj.d
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) 2002 by Digital Mars
|
||||
// All Rights Reserved
|
||||
// written by Walter Bright
|
||||
// www.digitalmars.com
|
||||
|
||||
module rt.obj;
|
||||
|
||||
extern (C):
|
||||
|
||||
/********************************
|
||||
* Compiler helper for operator == for class objects.
|
||||
*/
|
||||
|
||||
int _d_obj_eq(Object o1, Object o2)
|
||||
{
|
||||
return o1 is o2 || (o1 && o1.opEquals(o2));
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
* Compiler helper for operator <, <=, >, >= for class objects.
|
||||
*/
|
||||
|
||||
int _d_obj_cmp(Object o1, Object o2)
|
||||
{
|
||||
return o1.opCmp(o2);
|
||||
}
|
||||
1517
druntime/src/compiler/dmd/object_.d
Normal file
1517
druntime/src/compiler/dmd/object_.d
Normal file
File diff suppressed because it is too large
Load Diff
178
druntime/src/compiler/dmd/posix.mak
Normal file
178
druntime/src/compiler/dmd/posix.mak
Normal file
@@ -0,0 +1,178 @@
|
||||
# Makefile to build the compiler runtime D library for Linux
|
||||
# Designed to work with GNU make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the compiler runtime library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=libdruntime-rt-dmd.a
|
||||
LIB_MASK=libdruntime-rt-dmd*.a
|
||||
|
||||
CP=cp -f
|
||||
RM=rm -f
|
||||
MD=mkdir -p
|
||||
|
||||
CFLAGS=-O $(ADD_CFLAGS)
|
||||
#CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=gcc
|
||||
LC=$(AR) -qsv
|
||||
DC=dmd
|
||||
|
||||
LIB_DEST=../../../lib
|
||||
|
||||
.SUFFIXES: .s .S .c .cpp .d .html .o
|
||||
|
||||
.s.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.S.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.o:
|
||||
g++ -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.o:
|
||||
$(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
lib : dmd.lib
|
||||
doc : dmd.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_BASE= \
|
||||
aaA.o \
|
||||
aApply.o \
|
||||
aApplyR.o \
|
||||
adi.o \
|
||||
alloca.o \
|
||||
arrayassign.o \
|
||||
arraybyte.o \
|
||||
arraycast.o \
|
||||
arraycat.o \
|
||||
arraydouble.o \
|
||||
arrayfloat.o \
|
||||
arrayint.o \
|
||||
arrayreal.o \
|
||||
arrayshort.o \
|
||||
cast_.o \
|
||||
cmath2.o \
|
||||
complex.o \
|
||||
cover.o \
|
||||
critical.o \
|
||||
deh2.o \
|
||||
dmain2.o \
|
||||
invariant.o \
|
||||
invariant_.o \
|
||||
lifetime.o \
|
||||
llmath.o \
|
||||
memory.o \
|
||||
memset.o \
|
||||
monitor.o \
|
||||
obj.o \
|
||||
object_.o \
|
||||
qsort.o \
|
||||
switch_.o \
|
||||
trace.o
|
||||
# NOTE: trace.obj and cover.obj are not necessary for a successful build
|
||||
# as both are used for debugging features (profiling and coverage)
|
||||
# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
|
||||
# minit.asm is not used by dmd for linux
|
||||
# NOTE: deh.o is only needed for Win32, linux uses deh2.o
|
||||
|
||||
OBJ_UTIL= \
|
||||
util/console.o \
|
||||
util/cpuid.o \
|
||||
util/ctype.o \
|
||||
util/string.o \
|
||||
util/utf.o
|
||||
|
||||
OBJ_TI= \
|
||||
typeinfo/ti_AC.o \
|
||||
typeinfo/ti_Acdouble.o \
|
||||
typeinfo/ti_Acfloat.o \
|
||||
typeinfo/ti_Acreal.o \
|
||||
typeinfo/ti_Adouble.o \
|
||||
typeinfo/ti_Afloat.o \
|
||||
typeinfo/ti_Ag.o \
|
||||
typeinfo/ti_Aint.o \
|
||||
typeinfo/ti_Along.o \
|
||||
typeinfo/ti_Areal.o \
|
||||
typeinfo/ti_Ashort.o \
|
||||
typeinfo/ti_byte.o \
|
||||
typeinfo/ti_C.o \
|
||||
typeinfo/ti_cdouble.o \
|
||||
typeinfo/ti_cfloat.o \
|
||||
typeinfo/ti_char.o \
|
||||
typeinfo/ti_creal.o \
|
||||
typeinfo/ti_dchar.o \
|
||||
typeinfo/ti_delegate.o \
|
||||
typeinfo/ti_double.o \
|
||||
typeinfo/ti_float.o \
|
||||
typeinfo/ti_idouble.o \
|
||||
typeinfo/ti_ifloat.o \
|
||||
typeinfo/ti_int.o \
|
||||
typeinfo/ti_ireal.o \
|
||||
typeinfo/ti_long.o \
|
||||
typeinfo/ti_ptr.o \
|
||||
typeinfo/ti_real.o \
|
||||
typeinfo/ti_short.o \
|
||||
typeinfo/ti_ubyte.o \
|
||||
typeinfo/ti_uint.o \
|
||||
typeinfo/ti_ulong.o \
|
||||
typeinfo/ti_ushort.o \
|
||||
typeinfo/ti_void.o \
|
||||
typeinfo/ti_wchar.o
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_BASE) \
|
||||
$(OBJ_UTIL) \
|
||||
$(OBJ_TI)
|
||||
|
||||
######################################################
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
dmd.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) $@ $(ALL_OBJS)
|
||||
|
||||
dmd.doc : $(ALL_DOCS)
|
||||
echo No documentation available.
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
find . -name "*.di" | xargs $(RM)
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)/.
|
||||
158
druntime/src/compiler/dmd/qsort.d
Normal file
158
druntime/src/compiler/dmd/qsort.d
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
Portions of this file are:
|
||||
Copyright Prototronics, 1987
|
||||
Totem Lake P.O. 8117
|
||||
Kirkland, Washington 98034
|
||||
(206) 820-1972
|
||||
Licensed to Digital Mars.
|
||||
|
||||
June 11, 1987 from Ray Gardner's
|
||||
Denver, Colorado) public domain version
|
||||
|
||||
Use qsort2.d instead of this file if a redistributable version of
|
||||
_adSort() is required.
|
||||
*/
|
||||
|
||||
module rt.qsort;
|
||||
|
||||
/*
|
||||
** Sorts an array starting at base, of length nbr_elements, each
|
||||
** element of size width_bytes, ordered via compare_function; which
|
||||
** is called as (*comp_fp)(ptr_to_element1, ptr_to_element2)
|
||||
** and returns < 0 if element1 < element2, 0 if element1 = element2,
|
||||
** > 0 if element1 > element2. Most of the refinements are due to
|
||||
** R. Sedgewick. See "Implementing Quicksort Programs", Comm. ACM,
|
||||
** Oct. 1978, and Corrigendum, Comm. ACM, June 1979.
|
||||
*/
|
||||
|
||||
//debug=qsort; // uncomment to turn on debugging printf's
|
||||
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
|
||||
private const int _maxspan = 7; // subarrays of _maxspan or fewer elements
|
||||
// will be sorted by a simple insertion sort
|
||||
|
||||
/* Adjust _maxspan according to relative cost of a swap and a compare. Reduce
|
||||
_maxspan (not less than 1) if a swap is very expensive such as when you have
|
||||
an array of large structures to be sorted, rather than an array of pointers to
|
||||
structures. The default value is optimized for a high cost for compares. */
|
||||
|
||||
|
||||
extern (C) long _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
byte* base;
|
||||
byte*[40] stack; // stack
|
||||
byte** sp; // stack pointer
|
||||
byte* i, j, limit; // scan and limit pointers
|
||||
uint thresh; // size of _maxspan elements in bytes
|
||||
uint width = ti.tsize();
|
||||
|
||||
base = cast(byte *)a.ptr;
|
||||
thresh = _maxspan * width; // init threshold
|
||||
sp = stack.ptr; // init stack pointer
|
||||
limit = base + a.length * width; // pointer past end of array
|
||||
while (1) // repeat until done then return
|
||||
{
|
||||
while (limit - base > thresh) // if more than _maxspan elements
|
||||
{
|
||||
//swap middle, base
|
||||
ti.swap((cast(uint)(limit - base) >> 1) -
|
||||
(((cast(uint)(limit - base) >> 1)) % width) + base, base);
|
||||
|
||||
i = base + width; // i scans from left to right
|
||||
j = limit - width; // j scans from right to left
|
||||
|
||||
if (ti.compare(i, j) > 0) // Sedgewick's
|
||||
ti.swap(i, j); // three-element sort
|
||||
if (ti.compare(base, j) > 0) // sets things up
|
||||
ti.swap(base, j); // so that
|
||||
if (ti.compare(i, base) > 0) // *i <= *base <= *j
|
||||
ti.swap(i, base); // *base is the pivot element
|
||||
|
||||
while (1)
|
||||
{
|
||||
do // move i right until *i >= pivot
|
||||
i += width;
|
||||
while (ti.compare(i, base) < 0);
|
||||
do // move j left until *j <= pivot
|
||||
j -= width;
|
||||
while (ti.compare(j, base) > 0);
|
||||
if (i > j) // break loop if pointers crossed
|
||||
break;
|
||||
ti.swap(i, j); // else swap elements, keep scanning
|
||||
}
|
||||
ti.swap(base, j); // move pivot into correct place
|
||||
if (j - base > limit - i) // if left subarray is larger...
|
||||
{
|
||||
sp[0] = base; // stack left subarray base
|
||||
sp[1] = j; // and limit
|
||||
base = i; // sort the right subarray
|
||||
}
|
||||
else // else right subarray is larger
|
||||
{
|
||||
sp[0] = i; // stack right subarray base
|
||||
sp[1] = limit; // and limit
|
||||
limit = j; // sort the left subarray
|
||||
}
|
||||
sp += 2; // increment stack pointer
|
||||
assert(sp < cast(byte**)stack + stack.length);
|
||||
}
|
||||
|
||||
// Insertion sort on remaining subarray
|
||||
i = base + width;
|
||||
while (i < limit)
|
||||
{
|
||||
j = i;
|
||||
while (j > base && ti.compare(j - width, j) > 0)
|
||||
{
|
||||
ti.swap(j - width, j);
|
||||
j -= width;
|
||||
}
|
||||
i += width;
|
||||
}
|
||||
|
||||
if (sp > stack.ptr) // if any entries on stack...
|
||||
{
|
||||
sp -= 2; // pop the base and limit
|
||||
base = sp[0];
|
||||
limit = sp[1];
|
||||
}
|
||||
else // else stack empty, all done
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
72
druntime/src/compiler/dmd/qsort2.d
Normal file
72
druntime/src/compiler/dmd/qsort2.d
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
/*
|
||||
* Placed into Public Domain
|
||||
* written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*
|
||||
* This is a public domain version of qsort.d.
|
||||
* All it does is call C's qsort(), but runs a little slower since
|
||||
* it needs to synchronize a global variable.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.qsort2;
|
||||
|
||||
//debug=qsort;
|
||||
|
||||
private import stdc.stdlib;
|
||||
|
||||
struct Array
|
||||
{
|
||||
size_t length;
|
||||
void* ptr;
|
||||
}
|
||||
|
||||
private TypeInfo tiglobal;
|
||||
|
||||
extern (C) int cmp(void* p1, void* p2)
|
||||
{
|
||||
return tiglobal.compare(p1, p2);
|
||||
}
|
||||
|
||||
extern (C) long _adSort(Array a, TypeInfo ti)
|
||||
{
|
||||
synchronized
|
||||
{
|
||||
tiglobal = ti;
|
||||
qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
|
||||
}
|
||||
return *cast(long*)(&a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(qsort) printf("array.sort.unittest()\n");
|
||||
|
||||
int a[] = new int[10];
|
||||
|
||||
a[0] = 23;
|
||||
a[1] = 1;
|
||||
a[2] = 64;
|
||||
a[3] = 5;
|
||||
a[4] = 6;
|
||||
a[5] = 5;
|
||||
a[6] = 17;
|
||||
a[7] = 3;
|
||||
a[8] = 0;
|
||||
a[9] = -1;
|
||||
|
||||
a.sort;
|
||||
|
||||
for (int i = 0; i < a.length - 1; i++)
|
||||
{
|
||||
//printf("i = %d", i);
|
||||
//printf(" %d %d\n", a[i], a[i + 1]);
|
||||
assert(a[i] <= a[i + 1]);
|
||||
}
|
||||
}
|
||||
426
druntime/src/compiler/dmd/switch_.d
Normal file
426
druntime/src/compiler/dmd/switch_.d
Normal file
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.switch_;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
/******************************************************
|
||||
* Support for switch statements switching on strings.
|
||||
* Input:
|
||||
* table[] sorted array of strings generated by compiler
|
||||
* ca string to look up in table
|
||||
* Output:
|
||||
* result index of match in table[]
|
||||
* -1 if not in table
|
||||
*/
|
||||
|
||||
extern (C):
|
||||
|
||||
int _d_switch_string(char[][] table, char[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_string()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int ci;
|
||||
|
||||
ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
|
||||
assert(ci < 0); // ci==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int cj;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
assert(cj != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
cj = memcmp(table[i].ptr, ca.ptr, ca.length);
|
||||
if (cj == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_string(%.*s)\n", ca);
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
char[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
version (none)
|
||||
{
|
||||
// Print table
|
||||
printf("ca[] = '%s'\n", cast(char *)ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
}
|
||||
if (high &&
|
||||
ca.length >= table[0].length &&
|
||||
ca.length <= table[high - 1].length)
|
||||
{
|
||||
// Looking for 0 length string, which would only be at the beginning
|
||||
if (ca.length == 0)
|
||||
return 0;
|
||||
|
||||
char c1 = ca[0];
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = cast(ubyte)c1 - cast(ubyte)pca[0];
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(char []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_ustring(wchar[][] table, wchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_ustring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
wchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(wchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* Same thing, but for wide chars.
|
||||
*/
|
||||
|
||||
int _d_switch_dstring(dchar[][] table, dchar[] ca)
|
||||
in
|
||||
{
|
||||
//printf("in _d_switch_dstring()\n");
|
||||
assert(table.length >= 0);
|
||||
assert(ca.length >= 0);
|
||||
|
||||
// Make sure table[] is sorted correctly
|
||||
int j;
|
||||
|
||||
for (j = 1; j < table.length; j++)
|
||||
{
|
||||
int len1 = table[j - 1].length;
|
||||
int len2 = table[j].length;
|
||||
|
||||
assert(len1 <= len2);
|
||||
if (len1 == len2)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
|
||||
assert(c < 0); // c==0 means a duplicate
|
||||
}
|
||||
}
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
int i;
|
||||
int c;
|
||||
|
||||
//printf("out _d_switch_string()\n");
|
||||
if (result == -1)
|
||||
{
|
||||
// Not found
|
||||
for (i = 0; i < table.length; i++)
|
||||
{
|
||||
if (table[i].length == ca.length)
|
||||
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
assert(c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0 <= result && result < table.length);
|
||||
for (i = 0; 1; i++)
|
||||
{
|
||||
assert(i < table.length);
|
||||
if (table[i].length == ca.length)
|
||||
{
|
||||
c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{
|
||||
assert(i == result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body
|
||||
{
|
||||
//printf("body _d_switch_ustring()\n");
|
||||
int low;
|
||||
int high;
|
||||
int mid;
|
||||
int c;
|
||||
dchar[] pca;
|
||||
|
||||
low = 0;
|
||||
high = table.length;
|
||||
|
||||
/*
|
||||
// Print table
|
||||
wprintf("ca[] = '%.*s'\n", ca);
|
||||
for (mid = 0; mid < high; mid++)
|
||||
{
|
||||
pca = table[mid];
|
||||
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
|
||||
}
|
||||
*/
|
||||
|
||||
// Do binary search
|
||||
while (low < high)
|
||||
{
|
||||
mid = (low + high) >> 1;
|
||||
pca = table[mid];
|
||||
c = ca.length - pca.length;
|
||||
if (c == 0)
|
||||
{
|
||||
c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
|
||||
if (c == 0)
|
||||
{ //printf("found %d\n", mid);
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
{
|
||||
high = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
//printf("not found\n");
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
switch (cast(dchar []) "c")
|
||||
{
|
||||
case "coo":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
867
druntime/src/compiler/dmd/trace.d
Normal file
867
druntime/src/compiler/dmd/trace.d
Normal file
@@ -0,0 +1,867 @@
|
||||
|
||||
/* Trace dynamic profiler.
|
||||
* For use with the Digital Mars DMD compiler.
|
||||
* Copyright (C) 1995-2006 by Digital Mars
|
||||
* All Rights Reserved
|
||||
* Written by Walter Bright
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.trace;
|
||||
|
||||
private
|
||||
{
|
||||
import util.string;
|
||||
import stdc.ctype;
|
||||
import stdc.stdio;
|
||||
import stdc.string;
|
||||
import stdc.stdlib;
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
char* unmangle_ident(char*); // from DMC++ runtime library
|
||||
|
||||
alias long timer_t;
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
|
||||
struct SymPair
|
||||
{
|
||||
SymPair* next;
|
||||
Symbol* sym; // function that is called
|
||||
uint count; // number of times sym is called
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// A Symbol for each function name.
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
Symbol* Sl, Sr; // left, right children
|
||||
SymPair* Sfanin; // list of calling functions
|
||||
SymPair* Sfanout; // list of called functions
|
||||
timer_t totaltime; // aggregate time
|
||||
timer_t functime; // time excluding subfunction calls
|
||||
ubyte Sflags;
|
||||
char[] Sident; // name of symbol
|
||||
}
|
||||
|
||||
const ubyte SFvisited = 1; // visited
|
||||
|
||||
static Symbol* root; // root of symbol table
|
||||
|
||||
//////////////////////////////////
|
||||
// Build a linked list of these.
|
||||
|
||||
struct Stack
|
||||
{
|
||||
Stack* prev;
|
||||
Symbol* sym;
|
||||
timer_t starttime; // time when function was entered
|
||||
timer_t ohd; // overhead of all the bookkeeping code
|
||||
timer_t subtime; // time used by all subfunctions
|
||||
}
|
||||
|
||||
static Stack* stack_freelist;
|
||||
static Stack* trace_tos; // top of stack
|
||||
static int trace_inited; // !=0 if initialized
|
||||
static timer_t trace_ohd;
|
||||
|
||||
static Symbol** psymbols;
|
||||
static uint nsymbols; // number of symbols
|
||||
|
||||
static string trace_logfilename = "trace.log";
|
||||
static FILE* fplog;
|
||||
|
||||
static string trace_deffilename = "trace.def";
|
||||
static FILE* fpdef;
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
// Set file name for output.
|
||||
// A file name of "" means write results to stdout.
|
||||
// Returns:
|
||||
// 0 success
|
||||
// !=0 failure
|
||||
|
||||
int trace_setlogfilename(string name)
|
||||
{
|
||||
trace_logfilename = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Set file name for output.
|
||||
// A file name of "" means write results to stdout.
|
||||
// Returns:
|
||||
// 0 success
|
||||
// !=0 failure
|
||||
|
||||
int trace_setdeffilename(string name)
|
||||
{
|
||||
trace_deffilename = name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
// Output optimal function link order.
|
||||
|
||||
static void trace_order(Symbol *s)
|
||||
{
|
||||
while (s)
|
||||
{
|
||||
trace_place(s,0);
|
||||
if (s.Sl)
|
||||
trace_order(s.Sl);
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static Stack* stack_malloc()
|
||||
{ Stack *s;
|
||||
|
||||
if (stack_freelist)
|
||||
{ s = stack_freelist;
|
||||
stack_freelist = s.prev;
|
||||
}
|
||||
else
|
||||
s = cast(Stack *)trace_malloc(Stack.sizeof);
|
||||
return s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void stack_free(Stack *s)
|
||||
{
|
||||
s.prev = stack_freelist;
|
||||
stack_freelist = s;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Qsort() comparison routine for array of pointers to SymPair's.
|
||||
|
||||
static int sympair_cmp(in void* e1, in void* e2)
|
||||
{ SymPair** psp1;
|
||||
SymPair** psp2;
|
||||
|
||||
psp1 = cast(SymPair**)e1;
|
||||
psp2 = cast(SymPair**)e2;
|
||||
|
||||
return (*psp2).count - (*psp1).count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Place symbol s, and then place any fan ins or fan outs with
|
||||
// counts greater than count.
|
||||
|
||||
static void trace_place(Symbol *s, uint count)
|
||||
{ SymPair* sp;
|
||||
SymPair** base;
|
||||
|
||||
if (!(s.Sflags & SFvisited))
|
||||
{ size_t num;
|
||||
uint u;
|
||||
|
||||
//printf("\t%.*s\t%u\n", s.Sident, count);
|
||||
fprintf(fpdef,"\t%.*s\n", s.Sident);
|
||||
s.Sflags |= SFvisited;
|
||||
|
||||
// Compute number of items in array
|
||||
num = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
num++;
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
num++;
|
||||
if (!num)
|
||||
return;
|
||||
|
||||
// Allocate and fill array
|
||||
base = cast(SymPair**)trace_malloc(SymPair.sizeof * num);
|
||||
u = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
base[u++] = sp;
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
base[u++] = sp;
|
||||
|
||||
// Sort array
|
||||
qsort(base, num, (SymPair *).sizeof, &sympair_cmp);
|
||||
|
||||
//for (u = 0; u < num; u++)
|
||||
//printf("\t\t%.*s\t%u\n", base[u].sym.Sident, base[u].count);
|
||||
|
||||
// Place symbols
|
||||
for (u = 0; u < num; u++)
|
||||
{
|
||||
if (base[u].count >= count)
|
||||
{ uint u2;
|
||||
uint c2;
|
||||
|
||||
u2 = (u + 1 < num) ? u + 1 : u;
|
||||
c2 = base[u2].count;
|
||||
if (c2 < count)
|
||||
c2 = count;
|
||||
trace_place(base[u].sym,c2);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
trace_free(base);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
// Initialize and terminate.
|
||||
|
||||
static this()
|
||||
{
|
||||
trace_init();
|
||||
}
|
||||
|
||||
static ~this()
|
||||
{
|
||||
trace_term();
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
// Report results.
|
||||
// Also compute nsymbols.
|
||||
|
||||
static void trace_report(Symbol* s)
|
||||
{ SymPair* sp;
|
||||
uint count;
|
||||
|
||||
//printf("trace_report()\n");
|
||||
while (s)
|
||||
{ nsymbols++;
|
||||
if (s.Sl)
|
||||
trace_report(s.Sl);
|
||||
fprintf(fplog,"------------------\n");
|
||||
count = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
{
|
||||
fprintf(fplog,"\t%5d\t%.*s\n", sp.count, sp.sym.Sident);
|
||||
count += sp.count;
|
||||
}
|
||||
fprintf(fplog,"%.*s\t%u\t%lld\t%lld\n",s.Sident,count,s.totaltime,s.functime);
|
||||
for (sp = s.Sfanout; sp; sp = sp.next)
|
||||
{
|
||||
fprintf(fplog,"\t%5d\t%.*s\n",sp.count,sp.sym.Sident);
|
||||
}
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Allocate and fill array of symbols.
|
||||
|
||||
static void trace_array(Symbol *s)
|
||||
{ static uint u;
|
||||
|
||||
if (!psymbols)
|
||||
{ u = 0;
|
||||
psymbols = cast(Symbol **)trace_malloc((Symbol *).sizeof * nsymbols);
|
||||
}
|
||||
while (s)
|
||||
{
|
||||
psymbols[u++] = s;
|
||||
trace_array(s.Sl);
|
||||
s = s.Sr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// Qsort() comparison routine for array of pointers to Symbol's.
|
||||
|
||||
static int symbol_cmp(in void* e1, in void* e2)
|
||||
{ Symbol** ps1;
|
||||
Symbol** ps2;
|
||||
timer_t diff;
|
||||
|
||||
ps1 = cast(Symbol **)e1;
|
||||
ps2 = cast(Symbol **)e2;
|
||||
|
||||
diff = (*ps2).functime - (*ps1).functime;
|
||||
return (diff == 0) ? 0 : ((diff > 0) ? 1 : -1);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
// Report function timings
|
||||
|
||||
static void trace_times(Symbol* root)
|
||||
{ uint u;
|
||||
timer_t freq;
|
||||
|
||||
// Sort array
|
||||
qsort(psymbols, nsymbols, (Symbol *).sizeof, &symbol_cmp);
|
||||
|
||||
// Print array
|
||||
QueryPerformanceFrequency(&freq);
|
||||
fprintf(fplog,"\n======== Timer Is %lld Ticks/Sec, Times are in Microsecs ========\n\n",freq);
|
||||
fprintf(fplog," Num Tree Func Per\n");
|
||||
fprintf(fplog," Calls Time Time Call\n\n");
|
||||
for (u = 0; u < nsymbols; u++)
|
||||
{ Symbol* s = psymbols[u];
|
||||
timer_t tl,tr;
|
||||
timer_t fl,fr;
|
||||
timer_t pl,pr;
|
||||
timer_t percall;
|
||||
SymPair* sp;
|
||||
uint calls;
|
||||
char[] id;
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
char* p = (s.Sident ~ '\0').ptr;
|
||||
p = unmangle_ident(p);
|
||||
if (p)
|
||||
id = p[0 .. strlen(p)];
|
||||
}
|
||||
if (!id)
|
||||
id = s.Sident;
|
||||
calls = 0;
|
||||
for (sp = s.Sfanin; sp; sp = sp.next)
|
||||
calls += sp.count;
|
||||
if (calls == 0)
|
||||
calls = 1;
|
||||
|
||||
version (all)
|
||||
{
|
||||
tl = (s.totaltime * 1000000) / freq;
|
||||
fl = (s.functime * 1000000) / freq;
|
||||
percall = s.functime / calls;
|
||||
pl = (s.functime * 1000000) / calls / freq;
|
||||
|
||||
fprintf(fplog,"%7d%12lld%12lld%12lld %.*s\n",
|
||||
calls,tl,fl,pl,id);
|
||||
}
|
||||
else
|
||||
{
|
||||
tl = s.totaltime / freq;
|
||||
tr = ((s.totaltime - tl * freq) * 10000000) / freq;
|
||||
|
||||
fl = s.functime / freq;
|
||||
fr = ((s.functime - fl * freq) * 10000000) / freq;
|
||||
|
||||
percall = s.functime / calls;
|
||||
pl = percall / freq;
|
||||
pr = ((percall - pl * freq) * 10000000) / freq;
|
||||
|
||||
fprintf(fplog,"%7d\t%3lld.%07lld\t%3lld.%07lld\t%3lld.%07lld\t%.*s\n",
|
||||
calls,tl,tr,fl,fr,pl,pr,id);
|
||||
}
|
||||
if (id !is s.Sident)
|
||||
free(id.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
// Initialize.
|
||||
|
||||
static void trace_init()
|
||||
{
|
||||
if (!trace_inited)
|
||||
{
|
||||
trace_inited = 1;
|
||||
|
||||
{ // See if we can determine the overhead.
|
||||
uint u;
|
||||
timer_t starttime;
|
||||
timer_t endtime;
|
||||
Stack *st;
|
||||
|
||||
st = trace_tos;
|
||||
trace_tos = null;
|
||||
QueryPerformanceCounter(&starttime);
|
||||
for (u = 0; u < 100; u++)
|
||||
{
|
||||
asm
|
||||
{
|
||||
call _trace_pro_n ;
|
||||
db 0 ;
|
||||
call _trace_epi_n ;
|
||||
}
|
||||
}
|
||||
QueryPerformanceCounter(&endtime);
|
||||
trace_ohd = (endtime - starttime) / u;
|
||||
//printf("trace_ohd = %lld\n",trace_ohd);
|
||||
if (trace_ohd > 0)
|
||||
trace_ohd--; // round down
|
||||
trace_tos = st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Terminate.
|
||||
|
||||
void trace_term()
|
||||
{
|
||||
//printf("trace_term()\n");
|
||||
if (trace_inited == 1)
|
||||
{ Stack *n;
|
||||
|
||||
trace_inited = 2;
|
||||
|
||||
// Free remainder of the stack
|
||||
while (trace_tos)
|
||||
{
|
||||
n = trace_tos.prev;
|
||||
stack_free(trace_tos);
|
||||
trace_tos = n;
|
||||
}
|
||||
|
||||
while (stack_freelist)
|
||||
{
|
||||
n = stack_freelist.prev;
|
||||
stack_free(stack_freelist);
|
||||
stack_freelist = n;
|
||||
}
|
||||
|
||||
// Merge in data from any existing file
|
||||
trace_merge();
|
||||
|
||||
// Report results
|
||||
fplog = fopen(trace_logfilename.ptr, "w");
|
||||
if (fplog)
|
||||
{ nsymbols = 0;
|
||||
trace_report(root);
|
||||
trace_array(root);
|
||||
trace_times(root);
|
||||
fclose(fplog);
|
||||
}
|
||||
|
||||
// Output function link order
|
||||
fpdef = fopen(trace_deffilename.ptr,"w");
|
||||
if (fpdef)
|
||||
{ fprintf(fpdef,"\nFUNCTIONS\n");
|
||||
trace_order(root);
|
||||
fclose(fpdef);
|
||||
}
|
||||
|
||||
trace_free(psymbols);
|
||||
psymbols = null;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// Our storage allocator.
|
||||
|
||||
static void *trace_malloc(size_t nbytes)
|
||||
{ void *p;
|
||||
|
||||
p = malloc(nbytes);
|
||||
if (!p)
|
||||
exit(EXIT_FAILURE);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void trace_free(void *p)
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static Symbol* trace_addsym(char[] id)
|
||||
{
|
||||
Symbol** parent;
|
||||
Symbol* rover;
|
||||
Symbol* s;
|
||||
int cmp;
|
||||
char c;
|
||||
|
||||
//printf("trace_addsym('%s',%d)\n",p,len);
|
||||
parent = &root;
|
||||
rover = *parent;
|
||||
while (rover !is null) // while we haven't run out of tree
|
||||
{
|
||||
cmp = dstrcmp(id, rover.Sident);
|
||||
if (cmp == 0)
|
||||
{
|
||||
return rover;
|
||||
}
|
||||
parent = (cmp < 0) ? /* if we go down left side */
|
||||
&(rover.Sl) : /* then get left child */
|
||||
&(rover.Sr); /* else get right child */
|
||||
rover = *parent; /* get child */
|
||||
}
|
||||
/* not in table, so insert into table */
|
||||
s = cast(Symbol *)trace_malloc(Symbol.sizeof);
|
||||
memset(s,0,Symbol.sizeof);
|
||||
s.Sident = id;
|
||||
*parent = s; // link new symbol into tree
|
||||
return s;
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* Add symbol s with count to SymPair list.
|
||||
*/
|
||||
|
||||
static void trace_sympair_add(SymPair** psp, Symbol* s, uint count)
|
||||
{ SymPair* sp;
|
||||
|
||||
for (; 1; psp = &sp.next)
|
||||
{
|
||||
sp = *psp;
|
||||
if (!sp)
|
||||
{
|
||||
sp = cast(SymPair *)trace_malloc(SymPair.sizeof);
|
||||
sp.sym = s;
|
||||
sp.count = 0;
|
||||
sp.next = null;
|
||||
*psp = sp;
|
||||
break;
|
||||
}
|
||||
else if (sp.sym == s)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
sp.count += count;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void trace_pro(char[] id)
|
||||
{
|
||||
Stack* n;
|
||||
Symbol* s;
|
||||
timer_t starttime;
|
||||
timer_t t;
|
||||
|
||||
QueryPerformanceCounter(&starttime);
|
||||
if (id.length == 0)
|
||||
return;
|
||||
if (!trace_inited)
|
||||
trace_init(); // initialize package
|
||||
n = stack_malloc();
|
||||
n.prev = trace_tos;
|
||||
trace_tos = n;
|
||||
s = trace_addsym(id);
|
||||
trace_tos.sym = s;
|
||||
if (trace_tos.prev)
|
||||
{
|
||||
Symbol* prev;
|
||||
int i;
|
||||
|
||||
// Accumulate Sfanout and Sfanin
|
||||
prev = trace_tos.prev.sym;
|
||||
trace_sympair_add(&prev.Sfanout,s,1);
|
||||
trace_sympair_add(&s.Sfanin,prev,1);
|
||||
}
|
||||
QueryPerformanceCounter(&t);
|
||||
trace_tos.starttime = starttime;
|
||||
trace_tos.ohd = trace_ohd + t - starttime;
|
||||
trace_tos.subtime = 0;
|
||||
//printf("trace_tos.ohd=%lld, trace_ohd=%lld + t=%lld - starttime=%lld\n",
|
||||
// trace_tos.ohd,trace_ohd,t,starttime);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////
|
||||
//
|
||||
|
||||
static void trace_epi()
|
||||
{ Stack* n;
|
||||
timer_t endtime;
|
||||
timer_t t;
|
||||
timer_t ohd;
|
||||
|
||||
//printf("trace_epi()\n");
|
||||
if (trace_tos)
|
||||
{
|
||||
timer_t starttime;
|
||||
timer_t totaltime;
|
||||
|
||||
QueryPerformanceCounter(&endtime);
|
||||
starttime = trace_tos.starttime;
|
||||
totaltime = endtime - starttime - trace_tos.ohd;
|
||||
if (totaltime < 0)
|
||||
{ //printf("endtime=%lld - starttime=%lld - trace_tos.ohd=%lld < 0\n",
|
||||
// endtime,starttime,trace_tos.ohd);
|
||||
totaltime = 0; // round off error, just make it 0
|
||||
}
|
||||
|
||||
// totaltime is time spent in this function + all time spent in
|
||||
// subfunctions - bookkeeping overhead.
|
||||
trace_tos.sym.totaltime += totaltime;
|
||||
|
||||
//if (totaltime < trace_tos.subtime)
|
||||
//printf("totaltime=%lld < trace_tos.subtime=%lld\n",totaltime,trace_tos.subtime);
|
||||
trace_tos.sym.functime += totaltime - trace_tos.subtime;
|
||||
ohd = trace_tos.ohd;
|
||||
n = trace_tos.prev;
|
||||
stack_free(trace_tos);
|
||||
trace_tos = n;
|
||||
if (n)
|
||||
{ QueryPerformanceCounter(&t);
|
||||
n.ohd += ohd + t - endtime;
|
||||
n.subtime += totaltime;
|
||||
//printf("n.ohd = %lld\n",n.ohd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////// FILE INTERFACE /////////////////////////
|
||||
|
||||
/////////////////////////////////////
|
||||
// Read line from file fp.
|
||||
// Returns:
|
||||
// trace_malloc'd line buffer
|
||||
// null if end of file
|
||||
|
||||
static char* trace_readline(FILE* fp)
|
||||
{ int c;
|
||||
int dim;
|
||||
int i;
|
||||
char *buf;
|
||||
|
||||
//printf("trace_readline(%p)\n", fp);
|
||||
i = 0;
|
||||
dim = 0;
|
||||
buf = null;
|
||||
while (1)
|
||||
{
|
||||
if (i == dim)
|
||||
{ char *p;
|
||||
|
||||
dim += 80;
|
||||
p = cast(char *)trace_malloc(dim);
|
||||
memcpy(p,buf,i);
|
||||
trace_free(buf);
|
||||
buf = p;
|
||||
}
|
||||
c = fgetc(fp);
|
||||
switch (c)
|
||||
{
|
||||
case EOF:
|
||||
if (i == 0)
|
||||
{ trace_free(buf);
|
||||
return null;
|
||||
}
|
||||
case '\n':
|
||||
goto L1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
buf[i] = cast(char)c;
|
||||
i++;
|
||||
}
|
||||
L1:
|
||||
buf[i] = 0;
|
||||
//printf("line '%s'\n",buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// Skip space
|
||||
|
||||
static char *skipspace(char *p)
|
||||
{
|
||||
while (isspace(*p))
|
||||
p++;
|
||||
return p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// Merge in profiling data from existing file.
|
||||
|
||||
static void trace_merge()
|
||||
{ FILE *fp;
|
||||
char *buf;
|
||||
char *p;
|
||||
uint count;
|
||||
Symbol *s;
|
||||
SymPair *sfanin;
|
||||
SymPair **psp;
|
||||
|
||||
if (trace_logfilename && (fp = fopen(trace_logfilename.ptr,"r")) !is null)
|
||||
{
|
||||
buf = null;
|
||||
sfanin = null;
|
||||
psp = &sfanin;
|
||||
while (1)
|
||||
{
|
||||
trace_free(buf);
|
||||
buf = trace_readline(fp);
|
||||
if (!buf)
|
||||
break;
|
||||
switch (*buf)
|
||||
{
|
||||
case '=': // ignore rest of file
|
||||
trace_free(buf);
|
||||
goto L1;
|
||||
case ' ':
|
||||
case '\t': // fan in or fan out line
|
||||
count = strtoul(buf,&p,10);
|
||||
if (p == buf) // if invalid conversion
|
||||
continue;
|
||||
p = skipspace(p);
|
||||
if (!*p)
|
||||
continue;
|
||||
s = trace_addsym(p[0 .. strlen(p)]);
|
||||
trace_sympair_add(psp,s,count);
|
||||
break;
|
||||
default:
|
||||
if (!isalpha(*buf))
|
||||
{
|
||||
if (!sfanin)
|
||||
psp = &sfanin;
|
||||
continue; // regard unrecognized line as separator
|
||||
}
|
||||
case '?':
|
||||
case '_':
|
||||
case '$':
|
||||
case '@':
|
||||
p = buf;
|
||||
while (isgraph(*p))
|
||||
p++;
|
||||
*p = 0;
|
||||
//printf("trace_addsym('%s')\n",buf);
|
||||
s = trace_addsym(buf[0 .. strlen(buf)]);
|
||||
if (s.Sfanin)
|
||||
{ SymPair *sp;
|
||||
|
||||
for (; sfanin; sfanin = sp)
|
||||
{
|
||||
trace_sympair_add(&s.Sfanin,sfanin.sym,sfanin.count);
|
||||
sp = sfanin.next;
|
||||
trace_free(sfanin);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ s.Sfanin = sfanin;
|
||||
}
|
||||
sfanin = null;
|
||||
psp = &s.Sfanout;
|
||||
|
||||
{ timer_t t;
|
||||
|
||||
p++;
|
||||
count = strtoul(p,&p,10);
|
||||
t = cast(long)strtoull(p,&p,10);
|
||||
s.totaltime += t;
|
||||
t = cast(long)strtoull(p,&p,10);
|
||||
s.functime += t;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
L1:
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////// COMPILER INTERFACE /////////////////////
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Function called by trace code in function prolog.
|
||||
|
||||
void _trace_pro_n()
|
||||
{
|
||||
/* Length of string is either:
|
||||
* db length
|
||||
* ascii string
|
||||
* or:
|
||||
* db 0x0FF
|
||||
* db 0
|
||||
* dw length
|
||||
* ascii string
|
||||
*/
|
||||
|
||||
asm
|
||||
{ naked ;
|
||||
pushad ;
|
||||
mov ECX,8*4[ESP] ;
|
||||
xor EAX,EAX ;
|
||||
mov AL,[ECX] ;
|
||||
cmp AL,0xFF ;
|
||||
jne L1 ;
|
||||
cmp byte ptr 1[ECX],0 ;
|
||||
jne L1 ;
|
||||
mov AX,2[ECX] ;
|
||||
add 8*4[ESP],3 ;
|
||||
add ECX,3 ;
|
||||
L1: inc EAX ;
|
||||
inc ECX ;
|
||||
add 8*4[ESP],EAX ;
|
||||
dec EAX ;
|
||||
push ECX ;
|
||||
push EAX ;
|
||||
call trace_pro ;
|
||||
add ESP,8 ;
|
||||
popad ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Function called by trace code in function epilog.
|
||||
|
||||
|
||||
void _trace_epi_n()
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
pushad ;
|
||||
}
|
||||
trace_epi();
|
||||
asm
|
||||
{
|
||||
popad ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
extern (Windows)
|
||||
{
|
||||
export int QueryPerformanceCounter(timer_t *);
|
||||
export int QueryPerformanceFrequency(timer_t *);
|
||||
}
|
||||
}
|
||||
else version (X86)
|
||||
{
|
||||
extern (D)
|
||||
{
|
||||
void QueryPerformanceCounter(timer_t* ctr)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
mov ECX,EAX ;
|
||||
rdtsc ;
|
||||
mov [ECX],EAX ;
|
||||
mov 4[ECX],EDX ;
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
|
||||
void QueryPerformanceFrequency(timer_t* freq)
|
||||
{
|
||||
*freq = 3579545;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
95
druntime/src/compiler/dmd/typeinfo/ti_AC.d
Normal file
95
druntime/src/compiler/dmd/typeinfo/ti_AC.d
Normal file
@@ -0,0 +1,95 @@
|
||||
module rt.typeinfo.ti_AC;
|
||||
|
||||
// Object[]
|
||||
|
||||
class TypeInfo_AC : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{ Object[] s = *cast(Object[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
foreach (Object o; s)
|
||||
{
|
||||
if (o)
|
||||
hash += o.toHash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
|
||||
if (s1.length == s2.length)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
// Do not pass null's to Object.opEquals()
|
||||
if (o1 is o2 ||
|
||||
(!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
Object[] s1 = *cast(Object[]*)p1;
|
||||
Object[] s2 = *cast(Object[]*)p2;
|
||||
ptrdiff_t c;
|
||||
|
||||
c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
|
||||
if (c == 0)
|
||||
{
|
||||
for (size_t u = 0; u < s1.length; u++)
|
||||
{ Object o1 = s1[u];
|
||||
Object o2 = s2[u];
|
||||
|
||||
if (o1 is o2)
|
||||
continue;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (o1)
|
||||
{
|
||||
if (!o2)
|
||||
{ c = 1;
|
||||
break;
|
||||
}
|
||||
c = o1.opCmp(o2);
|
||||
if (c)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ c = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c < 0)
|
||||
c = -1;
|
||||
else if (c > 0)
|
||||
c = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (Object[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(Object);
|
||||
}
|
||||
}
|
||||
105
druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d
Normal file
105
druntime/src/compiler/dmd/typeinfo/ti_Acdouble.d
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acdouble;
|
||||
|
||||
private import typeinfo.ti_cdouble;
|
||||
|
||||
// cdouble[]
|
||||
|
||||
class TypeInfo_Ar : TypeInfo
|
||||
{
|
||||
override string toString() { return "cdouble[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ cdouble[] s = *cast(cdouble[]*)p;
|
||||
size_t len = s.length;
|
||||
cdouble *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_r._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
cdouble[] s1 = *cast(cdouble[]*)p1;
|
||||
cdouble[] s2 = *cast(cdouble[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_r._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (cdouble[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(cdouble);
|
||||
}
|
||||
}
|
||||
103
druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d
Normal file
103
druntime/src/compiler/dmd/typeinfo/ti_Acfloat.d
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acfloat;
|
||||
|
||||
private import typeinfo.ti_cfloat;
|
||||
|
||||
// cfloat[]
|
||||
|
||||
class TypeInfo_Aq : TypeInfo
|
||||
{
|
||||
override string toString() { return "cfloat[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ cfloat[] s = *cast(cfloat[]*)p;
|
||||
size_t len = s.length;
|
||||
cfloat *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_q._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
cfloat[] s1 = *cast(cfloat[]*)p1;
|
||||
cfloat[] s2 = *cast(cfloat[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_q._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (cfloat[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(cfloat);
|
||||
}
|
||||
}
|
||||
106
druntime/src/compiler/dmd/typeinfo/ti_Acreal.d
Normal file
106
druntime/src/compiler/dmd/typeinfo/ti_Acreal.d
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Acreal;
|
||||
|
||||
private import typeinfo.ti_creal;
|
||||
|
||||
// creal[]
|
||||
|
||||
class TypeInfo_Ac : TypeInfo
|
||||
{
|
||||
override string toString() { return "creal[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ creal[] s = *cast(creal[]*)p;
|
||||
size_t len = s.length;
|
||||
creal *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(uint *)str)[2];
|
||||
hash += (cast(uint *)str)[3];
|
||||
hash += (cast(uint *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_c._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
creal[] s1 = *cast(creal[]*)p1;
|
||||
creal[] s2 = *cast(creal[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_c._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (creal[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(creal);
|
||||
}
|
||||
}
|
||||
115
druntime/src/compiler/dmd/typeinfo/ti_Adouble.d
Normal file
115
druntime/src/compiler/dmd/typeinfo/ti_Adouble.d
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Adouble;
|
||||
|
||||
private import typeinfo.ti_double;
|
||||
|
||||
// double[]
|
||||
|
||||
class TypeInfo_Ad : TypeInfo
|
||||
{
|
||||
override string toString() { return "double[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ double[] s = *cast(double[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_d._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
double[] s1 = *cast(double[]*)p1;
|
||||
double[] s2 = *cast(double[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_d._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (double[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(double);
|
||||
}
|
||||
}
|
||||
|
||||
// idouble[]
|
||||
|
||||
class TypeInfo_Ap : TypeInfo_Ad
|
||||
{
|
||||
override string toString() { return "idouble[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(idouble);
|
||||
}
|
||||
}
|
||||
114
druntime/src/compiler/dmd/typeinfo/ti_Afloat.d
Normal file
114
druntime/src/compiler/dmd/typeinfo/ti_Afloat.d
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Afloat;
|
||||
|
||||
private import typeinfo.ti_float;
|
||||
|
||||
// float[]
|
||||
|
||||
class TypeInfo_Af : TypeInfo
|
||||
{
|
||||
override string toString() { return "float[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ float[] s = *cast(float[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return 0;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_f._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
float[] s1 = *cast(float[]*)p1;
|
||||
float[] s2 = *cast(float[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_f._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (float[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(float);
|
||||
}
|
||||
}
|
||||
|
||||
// ifloat[]
|
||||
|
||||
class TypeInfo_Ao : TypeInfo_Af
|
||||
{
|
||||
override string toString() { return "ifloat[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ifloat);
|
||||
}
|
||||
}
|
||||
204
druntime/src/compiler/dmd/typeinfo/ti_Ag.d
Normal file
204
druntime/src/compiler/dmd/typeinfo/ti_Ag.d
Normal file
@@ -0,0 +1,204 @@
|
||||
|
||||
module rt.typeinfo.ti_Ag;
|
||||
|
||||
private import util.string;
|
||||
private import stdc.string;
|
||||
|
||||
// byte[]
|
||||
|
||||
class TypeInfo_Ag : TypeInfo
|
||||
{
|
||||
override string toString() { return "byte[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ byte[] s = *cast(byte[]*)p;
|
||||
size_t len = s.length;
|
||||
byte *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
byte[] s1 = *cast(byte[]*)p1;
|
||||
byte[] s2 = *cast(byte[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(byte *)s1, cast(byte *)s2, s1.length) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
byte[] s1 = *cast(byte[]*)p1;
|
||||
byte[] s2 = *cast(byte[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (byte[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(byte);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ubyte[]
|
||||
|
||||
class TypeInfo_Ah : TypeInfo_Ag
|
||||
{
|
||||
override string toString() { return "ubyte[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
char[] s1 = *cast(char[]*)p1;
|
||||
char[] s2 = *cast(char[]*)p2;
|
||||
|
||||
return dstrcmp(s1, s2);
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ubyte);
|
||||
}
|
||||
}
|
||||
|
||||
// void[]
|
||||
|
||||
class TypeInfo_Av : TypeInfo_Ah
|
||||
{
|
||||
override string toString() { return "void[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(void);
|
||||
}
|
||||
}
|
||||
|
||||
// bool[]
|
||||
|
||||
class TypeInfo_Ab : TypeInfo_Ah
|
||||
{
|
||||
override string toString() { return "bool[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(bool);
|
||||
}
|
||||
}
|
||||
|
||||
// char[]
|
||||
|
||||
class TypeInfo_Aa : TypeInfo_Ag
|
||||
{
|
||||
override string toString() { return "char[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ char[] s = *cast(char[]*)p;
|
||||
hash_t hash = 0;
|
||||
|
||||
version (all)
|
||||
{
|
||||
foreach (char c; s)
|
||||
hash = hash * 11 + c;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t len = s.length;
|
||||
char *str = s;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ubyte *)str;
|
||||
return hash;
|
||||
|
||||
case 2:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
case 3:
|
||||
hash *= 9;
|
||||
hash += (*cast(ushort *)str << 8) +
|
||||
(cast(ubyte *)str)[2];
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 4;
|
||||
len -= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(char);
|
||||
}
|
||||
}
|
||||
129
druntime/src/compiler/dmd/typeinfo/ti_Aint.d
Normal file
129
druntime/src/compiler/dmd/typeinfo/ti_Aint.d
Normal file
@@ -0,0 +1,129 @@
|
||||
|
||||
module rt.typeinfo.ti_Aint;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// int[]
|
||||
|
||||
class TypeInfo_Ai : TypeInfo
|
||||
{
|
||||
override string toString() { return "int[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ int[] s = *cast(int[]*)p;
|
||||
auto len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * int.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
int[] s1 = *cast(int[]*)p1;
|
||||
int[] s2 = *cast(int[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (int[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(int);
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
int[][] a = [[5,3,8,7], [2,5,3,8,7]];
|
||||
a.sort;
|
||||
assert(a == [[2,5,3,8,7], [5,3,8,7]]);
|
||||
|
||||
a = [[5,3,8,7], [5,3,8]];
|
||||
a.sort;
|
||||
assert(a == [[5,3,8], [5,3,8,7]]);
|
||||
}
|
||||
|
||||
// uint[]
|
||||
|
||||
class TypeInfo_Ak : TypeInfo_Ai
|
||||
{
|
||||
override string toString() { return "uint[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
uint[] s1 = *cast(uint[]*)p1;
|
||||
uint[] s2 = *cast(uint[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(uint);
|
||||
}
|
||||
}
|
||||
|
||||
// dchar[]
|
||||
|
||||
class TypeInfo_Aw : TypeInfo_Ak
|
||||
{
|
||||
override string toString() { return "dchar[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(dchar);
|
||||
}
|
||||
}
|
||||
109
druntime/src/compiler/dmd/typeinfo/ti_Along.d
Normal file
109
druntime/src/compiler/dmd/typeinfo/ti_Along.d
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
module rt.typeinfo.ti_Along;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// long[]
|
||||
|
||||
class TypeInfo_Al : TypeInfo
|
||||
{
|
||||
override string toString() { return "long[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ long[] s = *cast(long[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str + *(cast(uint *)str + 1);
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * long.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
long[] s1 = *cast(long[]*)p1;
|
||||
long[] s2 = *cast(long[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (long[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(long);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ulong[]
|
||||
|
||||
class TypeInfo_Am : TypeInfo_Al
|
||||
{
|
||||
override string toString() { return "ulong[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
ulong[] s1 = *cast(ulong[]*)p1;
|
||||
ulong[] s2 = *cast(ulong[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (s1[u] < s2[u])
|
||||
return -1;
|
||||
else if (s1[u] > s2[u])
|
||||
return 1;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ulong);
|
||||
}
|
||||
}
|
||||
116
druntime/src/compiler/dmd/typeinfo/ti_Areal.d
Normal file
116
druntime/src/compiler/dmd/typeinfo/ti_Areal.d
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_Areal;
|
||||
|
||||
private import typeinfo.ti_real;
|
||||
|
||||
// real[]
|
||||
|
||||
class TypeInfo_Ae : TypeInfo
|
||||
{
|
||||
override string toString() { return "real[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ real[] s = *cast(real[]*)p;
|
||||
size_t len = s.length;
|
||||
auto str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
hash *= 9;
|
||||
hash += (cast(uint *)str)[0];
|
||||
hash += (cast(uint *)str)[1];
|
||||
hash += (cast(ushort *)str)[4];
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (len != s2.length)
|
||||
return false;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
if (!TypeInfo_e._equals(s1[u], s2[u]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
real[] s1 = *cast(real[]*)p1;
|
||||
real[] s2 = *cast(real[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int c = TypeInfo_e._compare(s1[u], s2[u]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (real[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(real);
|
||||
}
|
||||
}
|
||||
|
||||
// ireal[]
|
||||
|
||||
class TypeInfo_Aj : TypeInfo_Ae
|
||||
{
|
||||
override string toString() { return "ireal[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ireal);
|
||||
}
|
||||
}
|
||||
132
druntime/src/compiler/dmd/typeinfo/ti_Ashort.d
Normal file
132
druntime/src/compiler/dmd/typeinfo/ti_Ashort.d
Normal file
@@ -0,0 +1,132 @@
|
||||
|
||||
module rt.typeinfo.ti_Ashort;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
// short[]
|
||||
|
||||
class TypeInfo_As : TypeInfo
|
||||
{
|
||||
override string toString() { return "short[]"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{ short[] s = *cast(short[]*)p;
|
||||
size_t len = s.length;
|
||||
short *str = s.ptr;
|
||||
hash_t hash = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (len)
|
||||
{
|
||||
case 0:
|
||||
return hash;
|
||||
|
||||
case 1:
|
||||
hash *= 9;
|
||||
hash += *cast(ushort *)str;
|
||||
return hash;
|
||||
|
||||
default:
|
||||
hash *= 9;
|
||||
hash += *cast(uint *)str;
|
||||
str += 2;
|
||||
len -= 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
|
||||
return s1.length == s2.length &&
|
||||
memcmp(cast(void *)s1, cast(void *)s2, s1.length * short.sizeof) == 0;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
short[] s1 = *cast(short[]*)p1;
|
||||
short[] s2 = *cast(short[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (short[]).sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(short);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ushort[]
|
||||
|
||||
class TypeInfo_At : TypeInfo_As
|
||||
{
|
||||
override string toString() { return "ushort[]"; }
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
ushort[] s1 = *cast(ushort[]*)p1;
|
||||
ushort[] s2 = *cast(ushort[]*)p2;
|
||||
size_t len = s1.length;
|
||||
|
||||
if (s2.length < len)
|
||||
len = s2.length;
|
||||
for (size_t u = 0; u < len; u++)
|
||||
{
|
||||
int result = s1[u] - s2[u];
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
if (s1.length < s2.length)
|
||||
return -1;
|
||||
else if (s1.length > s2.length)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(ushort);
|
||||
}
|
||||
}
|
||||
|
||||
// wchar[]
|
||||
|
||||
class TypeInfo_Au : TypeInfo_At
|
||||
{
|
||||
override string toString() { return "wchar[]"; }
|
||||
|
||||
override TypeInfo next()
|
||||
{
|
||||
return typeid(wchar);
|
||||
}
|
||||
}
|
||||
74
druntime/src/compiler/dmd/typeinfo/ti_C.d
Normal file
74
druntime/src/compiler/dmd/typeinfo/ti_C.d
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
module rt.typeinfo.ti_C;
|
||||
|
||||
// Object
|
||||
|
||||
class TypeInfo_C : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
Object o = *cast(Object*)p;
|
||||
return o ? o.toHash() : 0;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
Object o1 = *cast(Object*)p1;
|
||||
Object o2 = *cast(Object*)p2;
|
||||
int c = 0;
|
||||
|
||||
// Regard null references as always being "less than"
|
||||
if (!(o1 is o2))
|
||||
{
|
||||
if (o1)
|
||||
{ if (!o2)
|
||||
c = 1;
|
||||
else
|
||||
c = o1.opCmp(o2);
|
||||
}
|
||||
else
|
||||
c = -1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return Object.sizeof;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_byte.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_byte.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// byte
|
||||
|
||||
module rt.typeinfo.ti_byte;
|
||||
|
||||
class TypeInfo_g : TypeInfo
|
||||
{
|
||||
override string toString() { return "byte"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(byte *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return byte.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
}
|
||||
66
druntime/src/compiler/dmd/typeinfo/ti_cdouble.d
Normal file
66
druntime/src/compiler/dmd/typeinfo/ti_cdouble.d
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
// cdouble
|
||||
|
||||
module rt.typeinfo.ti_cdouble;
|
||||
|
||||
class TypeInfo_r : TypeInfo
|
||||
{
|
||||
override string toString() { return "cdouble"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3];
|
||||
}
|
||||
|
||||
static equals_t _equals(cdouble f1, cdouble f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cdouble f1, cdouble f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return cdouble.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
cdouble t;
|
||||
|
||||
t = *cast(cdouble *)p1;
|
||||
*cast(cdouble *)p1 = *cast(cdouble *)p2;
|
||||
*cast(cdouble *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static cdouble r;
|
||||
|
||||
return (cast(cdouble *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
65
druntime/src/compiler/dmd/typeinfo/ti_cfloat.d
Normal file
65
druntime/src/compiler/dmd/typeinfo/ti_cfloat.d
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
// cfloat
|
||||
|
||||
module rt.typeinfo.ti_cfloat;
|
||||
|
||||
class TypeInfo_q : TypeInfo
|
||||
{
|
||||
override string toString() { return "cfloat"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static equals_t _equals(cfloat f1, cfloat f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(cfloat f1, cfloat f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return cfloat.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
cfloat t;
|
||||
|
||||
t = *cast(cfloat *)p1;
|
||||
*cast(cfloat *)p1 = *cast(cfloat *)p2;
|
||||
*cast(cfloat *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static cfloat r;
|
||||
|
||||
return (cast(cfloat *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_char.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_char.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
module rt.typeinfo.ti_char;
|
||||
|
||||
class TypeInfo_a : TypeInfo
|
||||
{
|
||||
override string toString() { return "char"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(char *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(char *)p1 == *cast(char *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(char *)p1 - *cast(char *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return char.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
char t;
|
||||
|
||||
t = *cast(char *)p1;
|
||||
*cast(char *)p1 = *cast(char *)p2;
|
||||
*cast(char *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static char c;
|
||||
|
||||
return (cast(char *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
67
druntime/src/compiler/dmd/typeinfo/ti_creal.d
Normal file
67
druntime/src/compiler/dmd/typeinfo/ti_creal.d
Normal file
@@ -0,0 +1,67 @@
|
||||
|
||||
// creal
|
||||
|
||||
module rt.typeinfo.ti_creal;
|
||||
|
||||
class TypeInfo_c : TypeInfo
|
||||
{
|
||||
override string toString() { return "creal"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
|
||||
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
|
||||
(cast(uint *)p)[4];
|
||||
}
|
||||
|
||||
static equals_t _equals(creal f1, creal f2)
|
||||
{
|
||||
return f1 == f2;
|
||||
}
|
||||
|
||||
static int _compare(creal f1, creal f2)
|
||||
{ int result;
|
||||
|
||||
if (f1.re < f2.re)
|
||||
result = -1;
|
||||
else if (f1.re > f2.re)
|
||||
result = 1;
|
||||
else if (f1.im < f2.im)
|
||||
result = -1;
|
||||
else if (f1.im > f2.im)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(creal *)p1, *cast(creal *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return creal.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
creal t;
|
||||
|
||||
t = *cast(creal *)p1;
|
||||
*cast(creal *)p1 = *cast(creal *)p2;
|
||||
*cast(creal *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static creal r;
|
||||
|
||||
return (cast(creal *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
44
druntime/src/compiler/dmd/typeinfo/ti_dchar.d
Normal file
44
druntime/src/compiler/dmd/typeinfo/ti_dchar.d
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
// dchar
|
||||
|
||||
module rt.typeinfo.ti_dchar;
|
||||
|
||||
class TypeInfo_w : TypeInfo
|
||||
{
|
||||
override string toString() { return "dchar"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(dchar *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dchar *)p1 == *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dchar *)p1 - *cast(dchar *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return dchar.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
dchar t;
|
||||
|
||||
t = *cast(dchar *)p1;
|
||||
*cast(dchar *)p1 = *cast(dchar *)p2;
|
||||
*cast(dchar *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static dchar c;
|
||||
|
||||
return (cast(dchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
39
druntime/src/compiler/dmd/typeinfo/ti_delegate.d
Normal file
39
druntime/src/compiler/dmd/typeinfo/ti_delegate.d
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
// delegate
|
||||
|
||||
module rt.typeinfo.ti_delegate;
|
||||
|
||||
alias void delegate(int) dg;
|
||||
|
||||
class TypeInfo_D : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{ long l = *cast(long *)p;
|
||||
|
||||
return cast(uint)(l + (l >> 32));
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(dg *)p1 == *cast(dg *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return dg.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
dg t;
|
||||
|
||||
t = *cast(dg *)p1;
|
||||
*cast(dg *)p1 = *cast(dg *)p2;
|
||||
*cast(dg *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_double.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_double.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// double
|
||||
|
||||
module rt.typeinfo.ti_double;
|
||||
|
||||
class TypeInfo_d : TypeInfo
|
||||
{
|
||||
override string toString() { return "double"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
static equals_t _equals(double f1, double f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(double d1, double d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(double *)p1, *cast(double *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return double.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
double t;
|
||||
|
||||
t = *cast(double *)p1;
|
||||
*cast(double *)p1 = *cast(double *)p2;
|
||||
*cast(double *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static double r;
|
||||
|
||||
return (cast(double *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_float.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_float.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// float
|
||||
|
||||
module rt.typeinfo.ti_float;
|
||||
|
||||
class TypeInfo_f : TypeInfo
|
||||
{
|
||||
override string toString() { return "float"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
static equals_t _equals(float f1, float f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(float d1, float d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(float *)p1, *cast(float *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return float.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
float t;
|
||||
|
||||
t = *cast(float *)p1;
|
||||
*cast(float *)p1 = *cast(float *)p2;
|
||||
*cast(float *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static float r;
|
||||
|
||||
return (cast(float *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_idouble.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_idouble.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// idouble
|
||||
|
||||
module rt.typeinfo.ti_idouble;
|
||||
|
||||
private import typeinfo.ti_double;
|
||||
|
||||
class TypeInfo_p : TypeInfo_d
|
||||
{
|
||||
override string toString() { return "idouble"; }
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_ifloat.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_ifloat.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// ifloat
|
||||
|
||||
module rt.typeinfo.ti_ifloat;
|
||||
|
||||
private import typeinfo.ti_float;
|
||||
|
||||
class TypeInfo_o : TypeInfo_f
|
||||
{
|
||||
override string toString() { return "ifloat"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_int.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_int.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// int
|
||||
|
||||
module rt.typeinfo.ti_int;
|
||||
|
||||
class TypeInfo_i : TypeInfo
|
||||
{
|
||||
override string toString() { return "int"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(int*) p1 < *cast(int*) p2)
|
||||
return -1;
|
||||
else if (*cast(int*) p1 > *cast(int*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return int.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(int *)p1;
|
||||
*cast(int *)p1 = *cast(int *)p2;
|
||||
*cast(int *)p2 = t;
|
||||
}
|
||||
}
|
||||
11
druntime/src/compiler/dmd/typeinfo/ti_ireal.d
Normal file
11
druntime/src/compiler/dmd/typeinfo/ti_ireal.d
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
// ireal
|
||||
|
||||
module rt.typeinfo.ti_ireal;
|
||||
|
||||
private import typeinfo.ti_real;
|
||||
|
||||
class TypeInfo_j : TypeInfo_e
|
||||
{
|
||||
override string toString() { return "ireal"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_long.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_long.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// long
|
||||
|
||||
module rt.typeinfo.ti_long;
|
||||
|
||||
class TypeInfo_l : TypeInfo
|
||||
{
|
||||
override string toString() { return "long"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(long *)p1 == *cast(long *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(long *)p1 < *cast(long *)p2)
|
||||
return -1;
|
||||
else if (*cast(long *)p1 > *cast(long *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return long.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
long t;
|
||||
|
||||
t = *cast(long *)p1;
|
||||
*cast(long *)p1 = *cast(long *)p2;
|
||||
*cast(long *)p2 = t;
|
||||
}
|
||||
}
|
||||
46
druntime/src/compiler/dmd/typeinfo/ti_ptr.d
Normal file
46
druntime/src/compiler/dmd/typeinfo/ti_ptr.d
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
// pointer
|
||||
|
||||
module rt.typeinfo.ti_ptr;
|
||||
|
||||
class TypeInfo_P : TypeInfo
|
||||
{
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return cast(uint)*cast(void* *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(void* *)p1 == *cast(void* *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
auto c = *cast(void* *)p1 - *cast(void* *)p2;
|
||||
if (c < 0)
|
||||
return -1;
|
||||
else if (c > 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return (void*).sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
void* t;
|
||||
|
||||
t = *cast(void* *)p1;
|
||||
*cast(void* *)p1 = *cast(void* *)p2;
|
||||
*cast(void* *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
64
druntime/src/compiler/dmd/typeinfo/ti_real.d
Normal file
64
druntime/src/compiler/dmd/typeinfo/ti_real.d
Normal file
@@ -0,0 +1,64 @@
|
||||
|
||||
// real
|
||||
|
||||
module rt.typeinfo.ti_real;
|
||||
|
||||
class TypeInfo_e : TypeInfo
|
||||
{
|
||||
override string toString() { return "real"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
|
||||
}
|
||||
|
||||
static equals_t _equals(real f1, real f2)
|
||||
{
|
||||
return f1 == f2 ||
|
||||
(f1 !<>= f1 && f2 !<>= f2);
|
||||
}
|
||||
|
||||
static int _compare(real d1, real d2)
|
||||
{
|
||||
if (d1 !<>= d2) // if either are NaN
|
||||
{
|
||||
if (d1 !<>= d1)
|
||||
{ if (d2 !<>= d2)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return _equals(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return _compare(*cast(real *)p1, *cast(real *)p2);
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return real.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
real t;
|
||||
|
||||
t = *cast(real *)p1;
|
||||
*cast(real *)p1 = *cast(real *)p2;
|
||||
*cast(real *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static real r;
|
||||
|
||||
return (cast(real *)&r)[0 .. 1];
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_short.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_short.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// short
|
||||
|
||||
module rt.typeinfo.ti_short;
|
||||
|
||||
class TypeInfo_s : TypeInfo
|
||||
{
|
||||
override string toString() { return "short"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(short *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(short *)p1 == *cast(short *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(short *)p1 - *cast(short *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return short.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
short t;
|
||||
|
||||
t = *cast(short *)p1;
|
||||
*cast(short *)p1 = *cast(short *)p2;
|
||||
*cast(short *)p2 = t;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_ubyte.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_ubyte.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// ubyte
|
||||
|
||||
module rt.typeinfo.ti_ubyte;
|
||||
|
||||
class TypeInfo_h : TypeInfo
|
||||
{
|
||||
override string toString() { return "ubyte"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(ubyte *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 == *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ubyte *)p1 - *cast(ubyte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ubyte.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ubyte t;
|
||||
|
||||
t = *cast(ubyte *)p1;
|
||||
*cast(ubyte *)p1 = *cast(ubyte *)p2;
|
||||
*cast(ubyte *)p2 = t;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeInfo_b : TypeInfo_h
|
||||
{
|
||||
override string toString() { return "bool"; }
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_uint.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_uint.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// uint
|
||||
|
||||
module rt.typeinfo.ti_uint;
|
||||
|
||||
class TypeInfo_k : TypeInfo
|
||||
{
|
||||
override string toString() { return "uint"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(uint *)p1 == *cast(uint *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(uint*) p1 < *cast(uint*) p2)
|
||||
return -1;
|
||||
else if (*cast(uint*) p1 > *cast(uint*) p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return uint.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
int t;
|
||||
|
||||
t = *cast(uint *)p1;
|
||||
*cast(uint *)p1 = *cast(uint *)p2;
|
||||
*cast(uint *)p2 = t;
|
||||
}
|
||||
}
|
||||
42
druntime/src/compiler/dmd/typeinfo/ti_ulong.d
Normal file
42
druntime/src/compiler/dmd/typeinfo/ti_ulong.d
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
// ulong
|
||||
|
||||
module rt.typeinfo.ti_ulong;
|
||||
|
||||
class TypeInfo_m : TypeInfo
|
||||
{
|
||||
override string toString() { return "ulong"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(uint *)p + (cast(uint *)p)[1];
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ulong *)p1 == *cast(ulong *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
if (*cast(ulong *)p1 < *cast(ulong *)p2)
|
||||
return -1;
|
||||
else if (*cast(ulong *)p1 > *cast(ulong *)p2)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ulong.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ulong t;
|
||||
|
||||
t = *cast(ulong *)p1;
|
||||
*cast(ulong *)p1 = *cast(ulong *)p2;
|
||||
*cast(ulong *)p2 = t;
|
||||
}
|
||||
}
|
||||
38
druntime/src/compiler/dmd/typeinfo/ti_ushort.d
Normal file
38
druntime/src/compiler/dmd/typeinfo/ti_ushort.d
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
// ushort
|
||||
|
||||
module rt.typeinfo.ti_ushort;
|
||||
|
||||
class TypeInfo_t : TypeInfo
|
||||
{
|
||||
override string toString() { return "ushort"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(ushort *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ushort *)p1 == *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(ushort *)p1 - *cast(ushort *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return ushort.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
ushort t;
|
||||
|
||||
t = *cast(ushort *)p1;
|
||||
*cast(ushort *)p1 = *cast(ushort *)p2;
|
||||
*cast(ushort *)p2 = t;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_void.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_void.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
// void
|
||||
|
||||
module rt.typeinfo.ti_void;
|
||||
|
||||
class TypeInfo_v : TypeInfo
|
||||
{
|
||||
override string toString() { return "void"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 == *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(byte *)p1 - *cast(byte *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return void.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
byte t;
|
||||
|
||||
t = *cast(byte *)p1;
|
||||
*cast(byte *)p1 = *cast(byte *)p2;
|
||||
*cast(byte *)p2 = t;
|
||||
}
|
||||
|
||||
override uint flags()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
43
druntime/src/compiler/dmd/typeinfo/ti_wchar.d
Normal file
43
druntime/src/compiler/dmd/typeinfo/ti_wchar.d
Normal file
@@ -0,0 +1,43 @@
|
||||
|
||||
module rt.typeinfo.ti_wchar;
|
||||
|
||||
|
||||
class TypeInfo_u : TypeInfo
|
||||
{
|
||||
override string toString() { return "wchar"; }
|
||||
|
||||
override hash_t getHash(in void* p)
|
||||
{
|
||||
return *cast(wchar *)p;
|
||||
}
|
||||
|
||||
override equals_t equals(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(wchar *)p1 == *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
override int compare(in void* p1, in void* p2)
|
||||
{
|
||||
return *cast(wchar *)p1 - *cast(wchar *)p2;
|
||||
}
|
||||
|
||||
override size_t tsize()
|
||||
{
|
||||
return wchar.sizeof;
|
||||
}
|
||||
|
||||
override void swap(void *p1, void *p2)
|
||||
{
|
||||
wchar t;
|
||||
|
||||
t = *cast(wchar *)p1;
|
||||
*cast(wchar *)p1 = *cast(wchar *)p2;
|
||||
*cast(wchar *)p2 = t;
|
||||
}
|
||||
|
||||
override void[] init()
|
||||
{ static wchar c;
|
||||
|
||||
return (cast(wchar *)&c)[0 .. 1];
|
||||
}
|
||||
}
|
||||
49
druntime/src/compiler/dmd/util/console.d
Normal file
49
druntime/src/compiler/dmd/util/console.d
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* The console module contains some simple routines for console output.
|
||||
*
|
||||
* Copyright: Public Domain
|
||||
* License: Public Domain
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module rt.util.console;
|
||||
|
||||
|
||||
private
|
||||
{
|
||||
version (Windows)
|
||||
{
|
||||
import sys.windows.windows;
|
||||
}
|
||||
else version( Posix )
|
||||
{
|
||||
import stdc.posix.unistd;
|
||||
}
|
||||
import util.string;
|
||||
}
|
||||
|
||||
|
||||
struct Console
|
||||
{
|
||||
Console opCall( in char[] val )
|
||||
{
|
||||
version( Windows )
|
||||
{
|
||||
uint count = void;
|
||||
WriteFile( GetStdHandle( 0xfffffff5 ), val.ptr, val.length, &count, null );
|
||||
}
|
||||
else version( Posix )
|
||||
{
|
||||
write( 2, val.ptr, val.length );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Console opCall( uint val )
|
||||
{
|
||||
char[10] tmp = void;
|
||||
return opCall( tmp.intToString( val ) );
|
||||
}
|
||||
}
|
||||
|
||||
Console console;
|
||||
464
druntime/src/compiler/dmd/util/cpuid.d
Normal file
464
druntime/src/compiler/dmd/util/cpuid.d
Normal file
@@ -0,0 +1,464 @@
|
||||
/**
|
||||
* Identify the characteristics of the host CPU.
|
||||
*
|
||||
* Implemented according to:
|
||||
|
||||
- AP-485 Intel(C) Processor Identification and the CPUID Instruction
|
||||
$(LINK http://www.intel.com/design/xeon/applnots/241618.htm)
|
||||
|
||||
- Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 2A: Instruction Set Reference, A-M
|
||||
$(LINK http://developer.intel.com/design/pentium4/manuals/index_new.htm)
|
||||
|
||||
- AMD CPUID Specification Publication # 25481
|
||||
$(LINK http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf)
|
||||
|
||||
Example:
|
||||
---
|
||||
import std.cpuid;
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
writefln(std.cpuid.toString());
|
||||
}
|
||||
---
|
||||
|
||||
AUTHORS: Tomas Lindquist Olsen <tomas@famolsen.dk>
|
||||
(slightly altered by Walter Bright)
|
||||
COPYRIGHT: Public Domain
|
||||
|
||||
* BUGS: Only works on x86 CPUs
|
||||
*
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdCpuid
|
||||
* COPYRIGHT = Public Domain
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly for use with the D Runtime Project
|
||||
*/
|
||||
|
||||
module rt.util.cpuid;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
version(D_InlineAsm_X86)
|
||||
{
|
||||
/// Returns vendor string
|
||||
char[] vendor() {return vendorStr;}
|
||||
/// Returns processor string
|
||||
string processor() {return processorStr;}
|
||||
|
||||
/// Is MMX supported?
|
||||
bool mmx() {return (flags&MMX_BIT)!=0;}
|
||||
/// Is FXSR supported?
|
||||
bool fxsr() {return (flags&FXSR_BIT)!=0;}
|
||||
/// Is SSE supported?
|
||||
bool sse() {return (flags&SSE_BIT)!=0;}
|
||||
/// Is SSE2 supported?
|
||||
bool sse2() {return (flags&SSE2_BIT)!=0;}
|
||||
/// Is SSE3 supported?
|
||||
bool sse3() {return (misc&SSE3_BIT)!=0;}
|
||||
/// Is SSSE3 supported?
|
||||
bool ssse3() {return (misc&SSSE3_BIT)!=0;}
|
||||
|
||||
/// Is AMD 3DNOW supported?
|
||||
bool amd3dnow() {return (exflags&AMD_3DNOW_BIT)!=0;}
|
||||
/// Is AMD 3DNOW Ext supported?
|
||||
bool amd3dnowExt() {return (exflags&AMD_3DNOW_EXT_BIT)!=0;}
|
||||
/// Is AMD MMX supported?
|
||||
bool amdMmx() {return (exflags&AMD_MMX_BIT)!=0;}
|
||||
|
||||
/// Is this an Intel Architecture IA64?
|
||||
bool ia64() {return (flags&IA64_BIT)!=0;}
|
||||
/// Is this an AMD 64?
|
||||
bool amd64() {return (exflags&AMD64_BIT)!=0;}
|
||||
|
||||
/// Is hyperthreading supported?
|
||||
bool hyperThreading() {return (flags&HTT_BIT)!=0;}
|
||||
/// Returns number of threads per CPU
|
||||
uint threadsPerCPU() {return maxThreads;}
|
||||
/// Returns number of cores in CPU
|
||||
uint coresPerCPU() {return maxCores;}
|
||||
|
||||
/// Is this an Intel processor?
|
||||
bool intel() {return manufac==INTEL;}
|
||||
/// Is this an AMD processor?
|
||||
bool amd() {return manufac==AMD;}
|
||||
|
||||
/// Returns stepping
|
||||
uint stepping() {return _stepping;}
|
||||
/// Returns model
|
||||
uint model() {return _model;}
|
||||
/// Returns family
|
||||
uint family() {return _family;}
|
||||
//uint processorType() {return (signature>>>12)&0x3;}
|
||||
|
||||
static this()
|
||||
{
|
||||
getVendorString();
|
||||
getProcessorString();
|
||||
getFeatureFlags();
|
||||
|
||||
// stepping / family / model
|
||||
_stepping = signature&0xF;
|
||||
uint fbase = (signature>>>8)&0xF;
|
||||
uint fex = (signature>>>20)&0xFF;
|
||||
uint mbase = (signature>>>4)&0xF;
|
||||
uint mex = (signature>>>16)&0xF;
|
||||
|
||||
// vendor specific
|
||||
void function() threadFn;
|
||||
switch(vendorStr)
|
||||
{
|
||||
case "GenuineIntel":
|
||||
manufac = INTEL;
|
||||
threadFn = &getThreadingIntel;
|
||||
if (fbase == 0xF)
|
||||
_family = fbase+fex;
|
||||
else
|
||||
_family = fbase;
|
||||
if (_family == 0x6 || _family == 0xF)
|
||||
_model = mbase+(mex<<4);
|
||||
else
|
||||
_model = mbase;
|
||||
break;
|
||||
|
||||
case "AuthenticAMD":
|
||||
manufac = AMD;
|
||||
threadFn = &getThreadingAMD;
|
||||
if (fbase < 0xF)
|
||||
{
|
||||
_family = fbase;
|
||||
_model = mbase;
|
||||
}
|
||||
else
|
||||
{
|
||||
_family = fbase+fex;
|
||||
_model = mbase+(mex<<4);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
manufac = OTHER;
|
||||
}
|
||||
|
||||
// threading details
|
||||
if (hyperThreading && threadFn !is null)
|
||||
{
|
||||
threadFn();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// feature flags
|
||||
enum : uint
|
||||
{
|
||||
MMX_BIT = 1<<23,
|
||||
FXSR_BIT = 1<<24,
|
||||
SSE_BIT = 1<<25,
|
||||
SSE2_BIT = 1<<26,
|
||||
HTT_BIT = 1<<28,
|
||||
IA64_BIT = 1<<30
|
||||
}
|
||||
// feature flags misc
|
||||
enum : uint
|
||||
{
|
||||
SSE3_BIT = 1,
|
||||
SSSE3_BIT = 1<<9
|
||||
}
|
||||
// extended feature flags
|
||||
enum : uint
|
||||
{
|
||||
AMD_MMX_BIT = 1<<22,
|
||||
AMD64_BIT = 1<<29,
|
||||
AMD_3DNOW_EXT_BIT = 1<<30,
|
||||
AMD_3DNOW_BIT = 1<<31
|
||||
}
|
||||
// manufacturer
|
||||
enum
|
||||
{
|
||||
OTHER,
|
||||
INTEL,
|
||||
AMD
|
||||
}
|
||||
|
||||
uint flags, misc, exflags, apic, signature;
|
||||
uint _stepping, _model, _family;
|
||||
|
||||
char[12] vendorStr = 0;
|
||||
string processorStr = "";
|
||||
|
||||
uint maxThreads=1;
|
||||
uint maxCores=1;
|
||||
uint manufac=OTHER;
|
||||
|
||||
/* **
|
||||
* fetches the cpu vendor string
|
||||
*/
|
||||
private void getVendorString()
|
||||
{
|
||||
char* dst = vendorStr.ptr;
|
||||
// puts the vendor string into dst
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
mov EAX, dst ;
|
||||
mov [EAX], EBX ;
|
||||
mov [EAX+4], EDX ;
|
||||
mov [EAX+8], ECX ;
|
||||
}
|
||||
}
|
||||
|
||||
private void getProcessorString()
|
||||
{
|
||||
char[48] buffer;
|
||||
char* dst = buffer.ptr;
|
||||
// puts the processor string into dst
|
||||
asm
|
||||
{
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0004 ;
|
||||
jb PSLabel ; // no support
|
||||
push EDI ;
|
||||
mov EDI, dst ;
|
||||
mov EAX, 0x8000_0002 ;
|
||||
cpuid ;
|
||||
mov [EDI], EAX ;
|
||||
mov [EDI+4], EBX ;
|
||||
mov [EDI+8], ECX ;
|
||||
mov [EDI+12], EDX ;
|
||||
mov EAX, 0x8000_0003 ;
|
||||
cpuid ;
|
||||
mov [EDI+16], EAX ;
|
||||
mov [EDI+20], EBX ;
|
||||
mov [EDI+24], ECX ;
|
||||
mov [EDI+28], EDX ;
|
||||
mov EAX, 0x8000_0004 ;
|
||||
cpuid ;
|
||||
mov [EDI+32], EAX ;
|
||||
mov [EDI+36], EBX ;
|
||||
mov [EDI+40], ECX ;
|
||||
mov [EDI+44], EDX ;
|
||||
pop EDI ;
|
||||
PSLabel: ;
|
||||
}
|
||||
|
||||
if (buffer[0] == char.init) // no support
|
||||
return;
|
||||
|
||||
// seems many intel processors prepend whitespace
|
||||
processorStr = cast(string)strip(toString(dst)).dup;
|
||||
}
|
||||
|
||||
private void getFeatureFlags()
|
||||
{
|
||||
uint f,m,e,a,s;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
cmp EAX, 1 ;
|
||||
jb FeatLabel ; // no support
|
||||
mov EAX, 1 ;
|
||||
cpuid ;
|
||||
mov f, EDX ;
|
||||
mov m, ECX ;
|
||||
mov a, EBX ;
|
||||
mov s, EAX ;
|
||||
|
||||
FeatLabel: ;
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0001 ;
|
||||
jb FeatLabel2 ; // no support
|
||||
mov EAX, 0x8000_0001 ;
|
||||
cpuid ;
|
||||
mov e, EDX ;
|
||||
|
||||
FeatLabel2:
|
||||
;
|
||||
}
|
||||
flags = f;
|
||||
misc = m;
|
||||
exflags = e;
|
||||
apic = a;
|
||||
signature = s;
|
||||
}
|
||||
|
||||
private void getThreadingIntel()
|
||||
{
|
||||
uint n;
|
||||
ubyte b = 0;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0 ;
|
||||
cpuid ;
|
||||
cmp EAX, 4 ;
|
||||
jb IntelSingle ;
|
||||
mov EAX, 4 ;
|
||||
mov ECX, 0 ;
|
||||
cpuid ;
|
||||
mov n, EAX ;
|
||||
mov b, 1 ;
|
||||
IntelSingle: ;
|
||||
}
|
||||
if (b != 0)
|
||||
{
|
||||
maxCores = ((n>>>26)&0x3F)+1;
|
||||
maxThreads = (apic>>>16)&0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxCores = maxThreads = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void getThreadingAMD()
|
||||
{
|
||||
ubyte n;
|
||||
ubyte b = 0;
|
||||
asm
|
||||
{
|
||||
mov EAX, 0x8000_0000 ;
|
||||
cpuid ;
|
||||
cmp EAX, 0x8000_0008 ;
|
||||
jb AMDSingle ;
|
||||
mov EAX, 0x8000_0008 ;
|
||||
cpuid ;
|
||||
mov n, CL ;
|
||||
mov b, 1 ;
|
||||
AMDSingle: ;
|
||||
}
|
||||
if (b != 0)
|
||||
{
|
||||
maxCores = n+1;
|
||||
maxThreads = (apic>>>16)&0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
maxCores = maxThreads = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* Support code for above, from std.string and std.ctype
|
||||
***************************************************************************/
|
||||
|
||||
private
|
||||
{
|
||||
enum
|
||||
{
|
||||
_SPC = 8,
|
||||
_CTL = 0x20,
|
||||
_BLK = 0x40,
|
||||
_HEX = 0x80,
|
||||
_UC = 1,
|
||||
_LC = 2,
|
||||
_PNC = 0x10,
|
||||
_DIG = 4,
|
||||
_ALP = _UC|_LC,
|
||||
}
|
||||
|
||||
ubyte _ctype[128] =
|
||||
[
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns !=0 if c is a space, tab, vertical tab, form feed,
|
||||
* carriage return, or linefeed.
|
||||
*/
|
||||
int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; }
|
||||
|
||||
/*****************************************
|
||||
* Strips leading or trailing whitespace, or both.
|
||||
*/
|
||||
char[] stripl(char[] s)
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = 0; i < s.length; i++)
|
||||
{
|
||||
if (!isspace(s[i]))
|
||||
break;
|
||||
}
|
||||
return s[i .. s.length];
|
||||
}
|
||||
|
||||
char[] stripr(char[] s) /// ditto
|
||||
{
|
||||
uint i;
|
||||
|
||||
for (i = s.length; i > 0; i--)
|
||||
{
|
||||
if (!isspace(s[i - 1]))
|
||||
break;
|
||||
}
|
||||
return s[0 .. i];
|
||||
}
|
||||
|
||||
char[] strip(char[] s) /// ditto
|
||||
{
|
||||
return stripr(stripl(s));
|
||||
}
|
||||
|
||||
char[] toString(char* s)
|
||||
{
|
||||
return s ? s[0 .. strlen(s)] : null;
|
||||
}
|
||||
|
||||
string toString(invariant(char)* s)
|
||||
{
|
||||
return s ? s[0 .. strlen(s)] : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] vendor() {return "unknown vendor"; }
|
||||
char[] processor() {return "unknown processor"; }
|
||||
|
||||
bool mmx() {return false; }
|
||||
bool fxsr() {return false; }
|
||||
bool sse() {return false; }
|
||||
bool sse2() {return false; }
|
||||
bool sse3() {return false; }
|
||||
bool ssse3() {return false; }
|
||||
|
||||
bool amd3dnow() {return false; }
|
||||
bool amd3dnowExt() {return false; }
|
||||
bool amdMmx() {return false; }
|
||||
|
||||
bool ia64() {return false; }
|
||||
bool amd64() {return false; }
|
||||
|
||||
bool hyperThreading() {return false; }
|
||||
uint threadsPerCPU() {return 0; }
|
||||
uint coresPerCPU() {return 0; }
|
||||
|
||||
bool intel() {return false; }
|
||||
bool amd() {return false; }
|
||||
|
||||
uint stepping() {return 0; }
|
||||
uint model() {return 0; }
|
||||
uint family() {return 0; }
|
||||
}
|
||||
106
druntime/src/compiler/dmd/util/ctype.d
Normal file
106
druntime/src/compiler/dmd/util/ctype.d
Normal file
@@ -0,0 +1,106 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
// Simple ASCII char classification functions
|
||||
|
||||
module rt.util.ctype;
|
||||
|
||||
int isalnum(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG) : 0; }
|
||||
int isalpha(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP) : 0; }
|
||||
int iscntrl(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_CTL) : 0; }
|
||||
int isdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_DIG) : 0; }
|
||||
int islower(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_LC) : 0; }
|
||||
int ispunct(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_PNC) : 0; }
|
||||
int isspace(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_SPC) : 0; }
|
||||
int isupper(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_UC) : 0; }
|
||||
int isxdigit(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_HEX) : 0; }
|
||||
int isgraph(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC) : 0; }
|
||||
int isprint(dchar c) { return (c <= 0x7F) ? _ctype[c] & (_ALP|_DIG|_PNC|_BLK) : 0; }
|
||||
int isascii(dchar c) { return c <= 0x7F; }
|
||||
|
||||
dchar tolower(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!isupper(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return isupper(c) ? c + (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
dchar toupper(dchar c)
|
||||
out (result)
|
||||
{
|
||||
assert(!islower(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
return islower(c) ? c - (cast(dchar)'a' - 'A') : c;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum
|
||||
{
|
||||
_SPC = 8,
|
||||
_CTL = 0x20,
|
||||
_BLK = 0x40,
|
||||
_HEX = 0x80,
|
||||
_UC = 1,
|
||||
_LC = 2,
|
||||
_PNC = 0x10,
|
||||
_DIG = 4,
|
||||
_ALP = _UC|_LC,
|
||||
}
|
||||
|
||||
ubyte _ctype[128] =
|
||||
[
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL|_SPC,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,_CTL,
|
||||
_SPC|_BLK,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,_DIG|_HEX,
|
||||
_PNC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC|_HEX,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_UC,_UC,_UC,_UC,_UC,
|
||||
_UC,_UC,_UC,_PNC,_PNC,_PNC,_PNC,_PNC,
|
||||
_PNC,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC|_HEX,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_LC,_LC,_LC,_LC,_LC,
|
||||
_LC,_LC,_LC,_PNC,_PNC,_PNC,_PNC,_CTL
|
||||
];
|
||||
|
||||
|
||||
unittest
|
||||
{
|
||||
assert(isspace(' '));
|
||||
assert(!isspace('z'));
|
||||
assert(toupper('a') == 'A');
|
||||
assert(tolower('Q') == 'q');
|
||||
assert(!isxdigit('G'));
|
||||
}
|
||||
35
druntime/src/compiler/dmd/util/string.d
Normal file
35
druntime/src/compiler/dmd/util/string.d
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The exception module defines all system-level exceptions and provides a
|
||||
* mechanism to alter system-level error handling.
|
||||
*
|
||||
* Copyright: Copyright (c) 2005-2008, The D Runtime Project
|
||||
* License: BSD Style, see LICENSE
|
||||
* Authors: Sean Kelly
|
||||
*/
|
||||
module rt.util.string;
|
||||
|
||||
private import stdc.string;
|
||||
|
||||
char[] intToString( char[] buf, uint val )
|
||||
{
|
||||
assert( buf.length > 9 );
|
||||
auto p = buf.ptr + buf.length;
|
||||
|
||||
do
|
||||
{
|
||||
*--p = cast(char)(val % 10 + '0');
|
||||
} while( val /= 10 );
|
||||
|
||||
return buf[p - buf.ptr .. $];
|
||||
}
|
||||
|
||||
|
||||
int dstrcmp( in char[] s1, in char[] s2 )
|
||||
{
|
||||
auto len = s1.length;
|
||||
if( s2.length < len )
|
||||
len = s2.length;
|
||||
if( memcmp( s1.ptr, s2.ptr, len ) == 0 )
|
||||
return 0;
|
||||
return s1.length > s2.length ? 1 : -1;
|
||||
}
|
||||
917
druntime/src/compiler/dmd/util/utf.d
Normal file
917
druntime/src/compiler/dmd/util/utf.d
Normal file
@@ -0,0 +1,917 @@
|
||||
// Written in the D programming language
|
||||
|
||||
/*
|
||||
* Copyright (C) 2003-2004 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/********************************************
|
||||
* Encode and decode UTF-8, UTF-16 and UTF-32 strings.
|
||||
*
|
||||
* For Win32 systems, the C wchar_t type is UTF-16 and corresponds to the D
|
||||
* wchar type.
|
||||
* For linux systems, the C wchar_t type is UTF-32 and corresponds to
|
||||
* the D utf.dchar type.
|
||||
*
|
||||
* UTF character support is restricted to (\u0000 <= character <= \U0010FFFF).
|
||||
*
|
||||
* See_Also:
|
||||
* $(LINK2 http://en.wikipedia.org/wiki/Unicode, Wikipedia)<br>
|
||||
* $(LINK http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)<br>
|
||||
* $(LINK http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335)
|
||||
* Macros:
|
||||
* WIKI = Phobos/StdUtf
|
||||
*/
|
||||
|
||||
module rt.util.utf;
|
||||
|
||||
|
||||
extern (C) void onUnicodeError( string msg, size_t idx );
|
||||
|
||||
/*******************************
|
||||
* Test if c is a valid UTF-32 character.
|
||||
*
|
||||
* \uFFFE and \uFFFF are considered valid by this function,
|
||||
* as they are permitted for internal use by an application,
|
||||
* but they are not allowed for interchange by the Unicode standard.
|
||||
*
|
||||
* Returns: true if it is, false if not.
|
||||
*/
|
||||
|
||||
bool isValidDchar(dchar c)
|
||||
{
|
||||
/* Note: FFFE and FFFF are specifically permitted by the
|
||||
* Unicode standard for application internal use, but are not
|
||||
* allowed for interchange.
|
||||
* (thanks to Arcane Jill)
|
||||
*/
|
||||
|
||||
return c < 0xD800 ||
|
||||
(c > 0xDFFF && c <= 0x10FFFF /*&& c != 0xFFFE && c != 0xFFFF*/);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.isValidDchar.unittest\n");
|
||||
assert(isValidDchar(cast(dchar)'a') == true);
|
||||
assert(isValidDchar(cast(dchar)0x1FFFFF) == false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
auto UTF8stride =
|
||||
[
|
||||
cast(ubyte)
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,0xFF,0xFF,
|
||||
];
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-8 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns:
|
||||
* The number of bytes in the UTF-8 sequence or
|
||||
* 0xFF meaning s[i] is not the start of of UTF-8 sequence.
|
||||
*/
|
||||
uint stride(in char[] s, size_t i)
|
||||
{
|
||||
return UTF8stride[s[i]];
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-16 sequence starting at index i
|
||||
* in string s.
|
||||
*/
|
||||
uint stride(in wchar[] s, size_t i)
|
||||
{ uint u = s[i];
|
||||
return 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* stride() returns the length of a UTF-32 sequence starting at index i
|
||||
* in string s.
|
||||
* Returns: The return value will always be 1.
|
||||
*/
|
||||
uint stride(in dchar[] s, size_t i)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*******************************************
|
||||
* Given an index i into an array of characters s[],
|
||||
* and assuming that index i is at the start of a UTF character,
|
||||
* determine the number of UCS characters up to that index i.
|
||||
*/
|
||||
|
||||
size_t toUCSindex(in char[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < i; )
|
||||
{
|
||||
j += stride(s, j);
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
onUnicodeError("invalid UTF-8 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUCSindex(in wchar[] s, size_t i)
|
||||
{
|
||||
size_t n;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < i; )
|
||||
{
|
||||
j += stride(s, j);
|
||||
n++;
|
||||
}
|
||||
if (j > i)
|
||||
{
|
||||
onUnicodeError("invalid UTF-16 sequence", j);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUCSindex(in dchar[] s, size_t i)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* Given a UCS index n into an array of characters s[], return the UTF index.
|
||||
*/
|
||||
|
||||
size_t toUTFindex(in char[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
uint j = UTF8stride[s[i]];
|
||||
if (j == 0xFF)
|
||||
onUnicodeError("invalid UTF-8 sequence", i);
|
||||
i += j;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUTFindex(in wchar[] s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
while (n--)
|
||||
{ wchar u = s[i];
|
||||
|
||||
i += 1 + (u >= 0xD800 && u <= 0xDBFF);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
size_t toUTFindex(in dchar[] s, size_t n)
|
||||
{
|
||||
return n;
|
||||
}
|
||||
|
||||
/* =================== Decode ======================= */
|
||||
|
||||
/***************
|
||||
* Decodes and returns character starting at s[idx]. idx is advanced past the
|
||||
* decoded character. If the character is not well formed, a UtfException is
|
||||
* thrown and idx remains unchanged.
|
||||
*/
|
||||
dchar decode(in char[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t len = s.length;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
char u = s[i];
|
||||
|
||||
if (u & 0x80)
|
||||
{ uint n;
|
||||
char u2;
|
||||
|
||||
/* The following encodings are valid, except for the 5 and 6 byte
|
||||
* combinations:
|
||||
* 0xxxxxxx
|
||||
* 110xxxxx 10xxxxxx
|
||||
* 1110xxxx 10xxxxxx 10xxxxxx
|
||||
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
*/
|
||||
for (n = 1; ; n++)
|
||||
{
|
||||
if (n > 4)
|
||||
goto Lerr; // only do the first 4 of 6 encodings
|
||||
if (((u << n) & 0x80) == 0)
|
||||
{
|
||||
if (n == 1)
|
||||
goto Lerr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Pick off (7 - n) significant bits of B from first byte of octet
|
||||
V = cast(dchar)(u & ((1 << (7 - n)) - 1));
|
||||
|
||||
if (i + (n - 1) >= len)
|
||||
goto Lerr; // off end of string
|
||||
|
||||
/* The following combinations are overlong, and illegal:
|
||||
* 1100000x (10xxxxxx)
|
||||
* 11100000 100xxxxx (10xxxxxx)
|
||||
* 11110000 1000xxxx (10xxxxxx 10xxxxxx)
|
||||
* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx)
|
||||
*/
|
||||
u2 = s[i + 1];
|
||||
if ((u & 0xFE) == 0xC0 ||
|
||||
(u == 0xE0 && (u2 & 0xE0) == 0x80) ||
|
||||
(u == 0xF0 && (u2 & 0xF0) == 0x80) ||
|
||||
(u == 0xF8 && (u2 & 0xF8) == 0x80) ||
|
||||
(u == 0xFC && (u2 & 0xFC) == 0x80))
|
||||
goto Lerr; // overlong combination
|
||||
|
||||
for (uint j = 1; j != n; j++)
|
||||
{
|
||||
u = s[i + j];
|
||||
if ((u & 0xC0) != 0x80)
|
||||
goto Lerr; // trailing bytes are 10xxxxxx
|
||||
V = (V << 6) | (u & 0x3F);
|
||||
}
|
||||
if (!isValidDchar(V))
|
||||
goto Lerr;
|
||||
i += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = cast(dchar) u;
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return V;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError("invalid UTF-8 sequence", i);
|
||||
return V; // dummy return
|
||||
}
|
||||
|
||||
unittest
|
||||
{ size_t i;
|
||||
dchar c;
|
||||
|
||||
debug(utf) printf("utf.decode.unittest\n");
|
||||
|
||||
static s1 = "abcd"c;
|
||||
i = 0;
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'a');
|
||||
assert(i == 1);
|
||||
c = decode(s1, i);
|
||||
assert(c == cast(dchar)'b');
|
||||
assert(i == 2);
|
||||
|
||||
static s2 = "\xC2\xA9"c;
|
||||
i = 0;
|
||||
c = decode(s2, i);
|
||||
assert(c == cast(dchar)'\u00A9');
|
||||
assert(i == 2);
|
||||
|
||||
static s3 = "\xE2\x89\xA0"c;
|
||||
i = 0;
|
||||
c = decode(s3, i);
|
||||
assert(c == cast(dchar)'\u2260');
|
||||
assert(i == 3);
|
||||
|
||||
static s4 =
|
||||
[ "\xE2\x89"c, // too short
|
||||
"\xC0\x8A",
|
||||
"\xE0\x80\x8A",
|
||||
"\xF0\x80\x80\x8A",
|
||||
"\xF8\x80\x80\x80\x8A",
|
||||
"\xFC\x80\x80\x80\x80\x8A",
|
||||
];
|
||||
|
||||
for (int j = 0; j < s4.length; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
i = 0;
|
||||
c = decode(s4[j], i);
|
||||
assert(0);
|
||||
}
|
||||
catch (Object o)
|
||||
{
|
||||
i = 23;
|
||||
}
|
||||
assert(i == 23);
|
||||
}
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(in wchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(isValidDchar(result));
|
||||
}
|
||||
body
|
||||
{
|
||||
string msg;
|
||||
dchar V;
|
||||
size_t i = idx;
|
||||
uint u = s[i];
|
||||
|
||||
if (u & ~0x7F)
|
||||
{ if (u >= 0xD800 && u <= 0xDBFF)
|
||||
{ uint u2;
|
||||
|
||||
if (i + 1 == s.length)
|
||||
{ msg = "surrogate UTF-16 high value past end of string";
|
||||
goto Lerr;
|
||||
}
|
||||
u2 = s[i + 1];
|
||||
if (u2 < 0xDC00 || u2 > 0xDFFF)
|
||||
{ msg = "surrogate UTF-16 low value out of range";
|
||||
goto Lerr;
|
||||
}
|
||||
u = ((u - 0xD7C0) << 10) + (u2 - 0xDC00);
|
||||
i += 2;
|
||||
}
|
||||
else if (u >= 0xDC00 && u <= 0xDFFF)
|
||||
{ msg = "unpaired surrogate UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else if (u == 0xFFFE || u == 0xFFFF)
|
||||
{ msg = "illegal UTF-16 value";
|
||||
goto Lerr;
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
idx = i;
|
||||
return cast(dchar)u;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError(msg, i);
|
||||
return cast(dchar)u; // dummy return
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
dchar decode(in dchar[] s, inout size_t idx)
|
||||
in
|
||||
{
|
||||
assert(idx >= 0 && idx < s.length);
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t i = idx;
|
||||
dchar c = s[i];
|
||||
|
||||
if (!isValidDchar(c))
|
||||
goto Lerr;
|
||||
idx = i + 1;
|
||||
return c;
|
||||
|
||||
Lerr:
|
||||
onUnicodeError("invalid UTF-32 value", i);
|
||||
return c; // dummy return
|
||||
}
|
||||
|
||||
|
||||
/* =================== Encode ======================= */
|
||||
|
||||
/*******************************
|
||||
* Encodes character c and appends it to array s[].
|
||||
*/
|
||||
void encode(inout char[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
char[] r = s;
|
||||
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
r ~= cast(char) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
char[4] buf;
|
||||
uint L;
|
||||
|
||||
if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 2;
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 3;
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
L = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
r ~= buf[0 .. L];
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.encode.unittest\n");
|
||||
|
||||
char[] s = "abcd".dup;
|
||||
encode(s, cast(dchar)'a');
|
||||
assert(s.length == 5);
|
||||
assert(s == "abcda");
|
||||
|
||||
encode(s, cast(dchar)'\u00A9');
|
||||
assert(s.length == 7);
|
||||
assert(s == "abcda\xC2\xA9");
|
||||
//assert(s == "abcda\u00A9"); // BUG: fix compiler
|
||||
|
||||
encode(s, cast(dchar)'\u2260');
|
||||
assert(s.length == 10);
|
||||
assert(s == "abcda\xC2\xA9\xE2\x89\xA0");
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
|
||||
void encode(inout wchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
wchar[] r = s;
|
||||
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
r ~= cast(wchar) c;
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar[2] buf;
|
||||
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
r ~= buf;
|
||||
}
|
||||
s = r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
void encode(inout dchar[] s, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
s ~= c;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the code length of $(D c) in the encoding using $(D C) as a
|
||||
code point. The code is returned in character count, not in bytes.
|
||||
*/
|
||||
|
||||
ubyte codeLength(C)(dchar c)
|
||||
{
|
||||
|
||||
static if (C.sizeof == 1)
|
||||
{
|
||||
return
|
||||
c <= 0x7F ? 1
|
||||
: c <= 0x7FF ? 2
|
||||
: c <= 0xFFFF ? 3
|
||||
: c <= 0x10FFFF ? 4
|
||||
: (assert(false), 6);
|
||||
}
|
||||
|
||||
else static if (C.sizeof == 2)
|
||||
{
|
||||
return c <= 0xFFFF ? 1 : 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(C.sizeof == 4);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* =================== Validation ======================= */
|
||||
|
||||
/***********************************
|
||||
Checks to see if string is well formed or not. $(D S) can be an array
|
||||
of $(D char), $(D wchar), or $(D dchar). Throws a $(D UtfException)
|
||||
if it is not. Use to check all untrusted input for correctness.
|
||||
*/
|
||||
void validate(S)(in S s)
|
||||
{
|
||||
auto len = s.length;
|
||||
for (size_t i = 0; i < len; )
|
||||
{
|
||||
decode(s, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF8 ======================= */
|
||||
|
||||
char[] toUTF8(char[4] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
buf[0] = cast(char) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else if (c <= 0x7FF)
|
||||
{
|
||||
buf[0] = cast(char)(0xC0 | (c >> 6));
|
||||
buf[1] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
else if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xE0 | (c >> 12));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 3];
|
||||
}
|
||||
else if (c <= 0x10FFFF)
|
||||
{
|
||||
buf[0] = cast(char)(0xF0 | (c >> 18));
|
||||
buf[1] = cast(char)(0x80 | ((c >> 12) & 0x3F));
|
||||
buf[2] = cast(char)(0x80 | ((c >> 6) & 0x3F));
|
||||
buf[3] = cast(char)(0x80 | (c & 0x3F));
|
||||
return buf[0 .. 4];
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Encodes string s into UTF-8 and returns the encoded string.
|
||||
*/
|
||||
string toUTF8(string s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
string toUTF8(in wchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ wchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar c; s[i .. slen])
|
||||
{
|
||||
encode(r, c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cast(string)r;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
string toUTF8(in dchar[] s)
|
||||
{
|
||||
char[] r;
|
||||
size_t i;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
|
||||
for (i = 0; i < slen; i++)
|
||||
{ dchar c = s[i];
|
||||
|
||||
if (c <= 0x7F)
|
||||
r[i] = cast(char)c; // fast path for ascii
|
||||
else
|
||||
{
|
||||
r.length = i;
|
||||
foreach (dchar d; s[i .. slen])
|
||||
{
|
||||
encode(r, d);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cast(string)r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF16 ======================= */
|
||||
|
||||
wchar[] toUTF16(wchar[2] buf, dchar c)
|
||||
in
|
||||
{
|
||||
assert(isValidDchar(c));
|
||||
}
|
||||
body
|
||||
{
|
||||
if (c <= 0xFFFF)
|
||||
{
|
||||
buf[0] = cast(wchar) c;
|
||||
return buf[0 .. 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = cast(wchar) ((((c - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
buf[1] = cast(wchar) (((c - 0x10000) & 0x3FF) + 0xDC00);
|
||||
return buf[0 .. 2];
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* Encodes string s into UTF-16 and returns the encoded string.
|
||||
* toUTF16z() is suitable for calling the 'W' functions in the Win32 API that take
|
||||
* an LPWSTR or LPCWSTR argument.
|
||||
*/
|
||||
wstring toUTF16(in char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
return cast(wstring)r;
|
||||
}
|
||||
|
||||
alias const(wchar)* wptr;
|
||||
/** ditto */
|
||||
wptr toUTF16z(in char[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen + 1;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c <= 0x7F)
|
||||
{
|
||||
i++;
|
||||
r ~= cast(wchar)c;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = decode(s, i);
|
||||
encode(r, c);
|
||||
}
|
||||
}
|
||||
r ~= "\000";
|
||||
return r.ptr;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
wstring toUTF16(wstring s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
wstring toUTF16(in dchar[] s)
|
||||
{
|
||||
wchar[] r;
|
||||
size_t slen = s.length;
|
||||
|
||||
r.length = slen;
|
||||
r.length = 0;
|
||||
for (size_t i = 0; i < slen; i++)
|
||||
{
|
||||
encode(r, s[i]);
|
||||
}
|
||||
return cast(wstring)r;
|
||||
}
|
||||
|
||||
/* =================== Conversion to UTF32 ======================= */
|
||||
|
||||
/*****
|
||||
* Encodes string s into UTF-32 and returns the encoded string.
|
||||
*/
|
||||
dstring toUTF32(in char[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return cast(dstring)r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
dstring toUTF32(in wchar[] s)
|
||||
{
|
||||
dchar[] r;
|
||||
size_t slen = s.length;
|
||||
size_t j = 0;
|
||||
|
||||
r.length = slen; // r[] will never be longer than s[]
|
||||
for (size_t i = 0; i < slen; )
|
||||
{
|
||||
dchar c = s[i];
|
||||
if (c >= 0x80)
|
||||
c = decode(s, i);
|
||||
else
|
||||
i++; // c is ascii, no need for decode
|
||||
r[j++] = c;
|
||||
}
|
||||
return cast(dstring)r[0 .. j];
|
||||
}
|
||||
|
||||
/** ditto */
|
||||
dstring toUTF32(dstring s)
|
||||
in
|
||||
{
|
||||
validate(s);
|
||||
}
|
||||
body
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
/* ================================ tests ================================== */
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(utf) printf("utf.toUTF.unittest\n");
|
||||
|
||||
auto c = "hello"c;
|
||||
auto w = toUTF16(c);
|
||||
assert(w == "hello");
|
||||
auto d = toUTF32(c);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hello");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hello");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hello");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hello");
|
||||
|
||||
|
||||
c = "hel\u1234o";
|
||||
w = toUTF16(c);
|
||||
assert(w == "hel\u1234o");
|
||||
d = toUTF32(c);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "hel\u1234o");
|
||||
d = toUTF32(w);
|
||||
assert(d == "hel\u1234o");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "hel\u1234o");
|
||||
w = toUTF16(d);
|
||||
assert(w == "hel\u1234o");
|
||||
|
||||
|
||||
c = "he\U0010AAAAllo";
|
||||
w = toUTF16(c);
|
||||
//foreach (wchar c; w) printf("c = x%x\n", c);
|
||||
//foreach (wchar c; cast(wstring)"he\U0010AAAAllo") printf("c = x%x\n", c);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
d = toUTF32(c);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(w);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
d = toUTF32(w);
|
||||
assert(d == "he\U0010AAAAllo");
|
||||
|
||||
c = toUTF8(d);
|
||||
assert(c == "he\U0010AAAAllo");
|
||||
w = toUTF16(d);
|
||||
assert(w == "he\U0010AAAAllo");
|
||||
}
|
||||
171
druntime/src/compiler/dmd/win32.mak
Normal file
171
druntime/src/compiler/dmd/win32.mak
Normal file
@@ -0,0 +1,171 @@
|
||||
# Makefile to build the compiler runtime D library for Win32
|
||||
# Designed to work with DigitalMars make
|
||||
# Targets:
|
||||
# make
|
||||
# Same as make all
|
||||
# make lib
|
||||
# Build the compiler runtime library
|
||||
# make doc
|
||||
# Generate documentation
|
||||
# make clean
|
||||
# Delete unneeded files created by build process
|
||||
|
||||
LIB_TARGET=druntime-rt-dmd.lib
|
||||
LIB_MASK=druntime-rt-dmd*.lib
|
||||
|
||||
CP=xcopy /y
|
||||
RM=del /f
|
||||
MD=mkdir
|
||||
|
||||
CFLAGS=-mn -6 -r $(ADD_CFLAGS)
|
||||
#CFLAGS=-g -mn -6 -r $(ADD_CFLAGS)
|
||||
|
||||
DFLAGS=-release -O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
TFLAGS=-O -inline -w -nofloat $(ADD_DFLAGS)
|
||||
#TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
CC=dmc
|
||||
LC=lib
|
||||
DC=dmd
|
||||
|
||||
LIB_DEST=..\..\..\lib
|
||||
|
||||
.DEFAULT: .asm .c .cpp .d .html .obj
|
||||
|
||||
.asm.obj:
|
||||
$(CC) -c $<
|
||||
|
||||
.c.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.cpp.obj:
|
||||
$(CC) -c $(CFLAGS) $< -o$@
|
||||
|
||||
.d.obj:
|
||||
$(DC) -c $(DFLAGS) $< -of$@
|
||||
|
||||
.d.html:
|
||||
$(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
|
||||
|
||||
targets : lib doc
|
||||
all : lib doc
|
||||
lib : dmd.lib
|
||||
doc : dmd.doc
|
||||
|
||||
######################################################
|
||||
|
||||
OBJ_BASE= \
|
||||
aaA.obj \
|
||||
aApply.obj \
|
||||
aApplyR.obj \
|
||||
adi.obj \
|
||||
arrayassign.obj \
|
||||
arraybyte.obj \
|
||||
arraycast.obj \
|
||||
arraycat.obj \
|
||||
arraydouble.obj \
|
||||
arrayfloat.obj \
|
||||
arrayint.obj \
|
||||
arrayreal.obj \
|
||||
arrayshort.obj \
|
||||
cast_.obj \
|
||||
complex.obj \
|
||||
cover.obj \
|
||||
critical.obj \
|
||||
deh.obj \
|
||||
dmain2.obj \
|
||||
invariant.obj \
|
||||
invariant_.obj \
|
||||
lifetime.obj \
|
||||
memory.obj \
|
||||
memset.obj \
|
||||
monitor.obj \
|
||||
obj.obj \
|
||||
object_.obj \
|
||||
qsort.obj \
|
||||
switch_.obj \
|
||||
trace.obj
|
||||
# NOTE: trace.obj and cover.obj are not necessary for a successful build
|
||||
# as both are used for debugging features (profiling and coverage)
|
||||
# NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and
|
||||
# minit.asm is not used by dmd for linux
|
||||
|
||||
OBJ_UTIL= \
|
||||
util\console.obj \
|
||||
util\cpuid.obj \
|
||||
util\ctype.obj \
|
||||
util\string.obj \
|
||||
util\utf.obj
|
||||
|
||||
OBJ_TI= \
|
||||
typeinfo\ti_AC.obj \
|
||||
typeinfo\ti_Acdouble.obj \
|
||||
typeinfo\ti_Acfloat.obj \
|
||||
typeinfo\ti_Acreal.obj \
|
||||
typeinfo\ti_Adouble.obj \
|
||||
typeinfo\ti_Afloat.obj \
|
||||
typeinfo\ti_Ag.obj \
|
||||
typeinfo\ti_Aint.obj \
|
||||
typeinfo\ti_Along.obj \
|
||||
typeinfo\ti_Areal.obj \
|
||||
typeinfo\ti_Ashort.obj \
|
||||
typeinfo\ti_byte.obj \
|
||||
typeinfo\ti_C.obj \
|
||||
typeinfo\ti_cdouble.obj \
|
||||
typeinfo\ti_cfloat.obj \
|
||||
typeinfo\ti_char.obj \
|
||||
typeinfo\ti_creal.obj \
|
||||
typeinfo\ti_dchar.obj \
|
||||
typeinfo\ti_delegate.obj \
|
||||
typeinfo\ti_double.obj \
|
||||
typeinfo\ti_float.obj \
|
||||
typeinfo\ti_idouble.obj \
|
||||
typeinfo\ti_ifloat.obj \
|
||||
typeinfo\ti_int.obj \
|
||||
typeinfo\ti_ireal.obj \
|
||||
typeinfo\ti_long.obj \
|
||||
typeinfo\ti_ptr.obj \
|
||||
typeinfo\ti_real.obj \
|
||||
typeinfo\ti_short.obj \
|
||||
typeinfo\ti_ubyte.obj \
|
||||
typeinfo\ti_uint.obj \
|
||||
typeinfo\ti_ulong.obj \
|
||||
typeinfo\ti_ushort.obj \
|
||||
typeinfo\ti_void.obj \
|
||||
typeinfo\ti_wchar.obj
|
||||
|
||||
ALL_OBJS= \
|
||||
$(OBJ_BASE) \
|
||||
$(OBJ_UTIL) \
|
||||
$(OBJ_TI)
|
||||
|
||||
######################################################
|
||||
|
||||
ALL_DOCS=
|
||||
|
||||
######################################################
|
||||
|
||||
dmd.lib : $(LIB_TARGET)
|
||||
|
||||
$(LIB_TARGET) : $(ALL_OBJS)
|
||||
$(RM) $@
|
||||
$(LC) -c -n $@ $(ALL_OBJS) minit.obj
|
||||
|
||||
dmd.doc : $(ALL_DOCS)
|
||||
@echo No documentation available.
|
||||
|
||||
######################################################
|
||||
|
||||
clean :
|
||||
$(RM) /s *.di
|
||||
$(RM) $(ALL_OBJS)
|
||||
$(RM) $(ALL_DOCS)
|
||||
$(RM) $(LIB_MASK)
|
||||
|
||||
install :
|
||||
$(MD) $(LIB_DEST)
|
||||
$(CP) $(LIB_MASK) $(LIB_DEST)\.
|
||||
414
druntime/src/compiler/ldc/aApply.d
Normal file
414
druntime/src/compiler/ldc/aApply.d
Normal file
@@ -0,0 +1,414 @@
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
//debug = apply;
|
||||
debug(apply)
|
||||
{
|
||||
extern(C) int printf(char*, ...);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
*/
|
||||
|
||||
// dg is D, but _aApplycd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplycd1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
d = decode(aa, i);
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw1(char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ d = decode(aa, i);
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
i++;
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc1(), len = %d\n", len);
|
||||
for (i = 0; i < len; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
d = decode(aa, i);
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
i++;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
|
||||
foreach (dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
// dg is D, but _aApplycd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywd2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
|
||||
d = aa[i];
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplycw2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
else
|
||||
n = 1;
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplywc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i += n)
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
char c;
|
||||
|
||||
w = aa[i];
|
||||
if (w & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
n = i;
|
||||
d = decode(aa, n);
|
||||
n -= i;
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)w;
|
||||
n = 1;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplydc2(), len = %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
d = aa[i];
|
||||
debug(apply) printf("d = %u\n", d);
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
debug(apply) printf("c2 = %d\n", c2);
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
|
||||
foreach (size_t i, dchar d; aa)
|
||||
{
|
||||
wchar w;
|
||||
auto j = i;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&j, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
975
druntime/src/compiler/ldc/aApplyR.d
Normal file
975
druntime/src/compiler/ldc/aApplyR.d
Normal file
@@ -0,0 +1,975 @@
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
/* This code handles decoding UTF strings for foreach_reverse loops.
|
||||
* There are 6 combinations of conversions between char, wchar,
|
||||
* and dchar, and 2 of each of those.
|
||||
*/
|
||||
|
||||
private import util.utf;
|
||||
|
||||
/**********************************************/
|
||||
/* 1 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
extern (C) int _aApplyRcd1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(dchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == '\U00100456'); break;
|
||||
case 2: assert(d == '\u1234'); break;
|
||||
case 3: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw1(in char[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc1(in wchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0;)
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = cast(char)d;
|
||||
}
|
||||
result = dg(cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(char d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xF4); break;
|
||||
case 2: assert(d == 0x80); break;
|
||||
case 3: assert(d == 0x91); break;
|
||||
case 4: assert(d == 0x96); break;
|
||||
case 5: assert(d == 0xE1); break;
|
||||
case 6: assert(d == 0x88); break;
|
||||
case 7: assert(d == 0xB4); break;
|
||||
case 8: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw1(in dchar[] aa, dg_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(wchar d; s)
|
||||
{
|
||||
//printf("i = %d, d = %x\n", i, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); break;
|
||||
case 1: assert(d == 0xDBC1); break;
|
||||
case 2: assert(d == 0xDC56); break;
|
||||
case 3: assert(d == 0x1234); break;
|
||||
case 4: assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* 2 argument versions */
|
||||
|
||||
// dg is D, but _aApplyRcd2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
extern (C) int _aApplyRcd2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
size_t i;
|
||||
size_t len = aa.length;
|
||||
|
||||
debug(apply) printf("_aApplyRcd2(), len = %d\n", len);
|
||||
for (i = len; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d & 0x80)
|
||||
{ char c = cast(char)d;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'b'); assert(k == 8); break;
|
||||
case 1: assert(d == '\U00100456'); assert(k == 4); break;
|
||||
case 2: assert(d == '\u1234'); assert(k == 1); break;
|
||||
case 3: assert(d == 'a'); assert(k == 0); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwd2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&d);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, dchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == '\U00100456'); break;
|
||||
case 2: assert(k == 1); assert(d == '\u1234'); break;
|
||||
case 3: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 4);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRcw2(in char[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
wchar w;
|
||||
|
||||
i--;
|
||||
w = aa[i];
|
||||
if (w & 0x80)
|
||||
{ char c = cast(char)w;
|
||||
uint j;
|
||||
uint m = 0x3F;
|
||||
d = 0;
|
||||
while ((c & 0xC0) != 0xC0)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-8 sequence", 0);
|
||||
i--;
|
||||
d |= (c & 0x3F) << j;
|
||||
j += 6;
|
||||
m >>= 1;
|
||||
c = aa[i];
|
||||
}
|
||||
d |= (c & m) << j;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 8); assert(d == 'b'); break;
|
||||
case 1: assert(k == 4); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 4); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRwc2(in wchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d;
|
||||
char c;
|
||||
|
||||
i--;
|
||||
d = aa[i];
|
||||
if (d >= 0xDC00 && d <= 0xDFFF)
|
||||
{ if (i == 0)
|
||||
onUnicodeError("Invalid UTF-16 sequence", 0);
|
||||
i--;
|
||||
d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00);
|
||||
}
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
c = cast(char)d;
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 4); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdc2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
char c;
|
||||
|
||||
if (d & ~0x7F)
|
||||
{
|
||||
char[4] buf;
|
||||
|
||||
auto b = toUTF8(buf, d);
|
||||
foreach (char c2; b)
|
||||
{
|
||||
result = dg(&i, cast(void *)&c2);
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{ c = cast(char)d;
|
||||
}
|
||||
result = dg(&i, cast(void *)&c);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, char d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xF4); break;
|
||||
case 2: assert(k == 2); assert(d == 0x80); break;
|
||||
case 3: assert(k == 2); assert(d == 0x91); break;
|
||||
case 4: assert(k == 2); assert(d == 0x96); break;
|
||||
case 5: assert(k == 1); assert(d == 0xE1); break;
|
||||
case 6: assert(k == 1); assert(d == 0x88); break;
|
||||
case 7: assert(k == 1); assert(d == 0xB4); break;
|
||||
case 8: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 9);
|
||||
}
|
||||
|
||||
/*****************************/
|
||||
|
||||
extern (C) int _aApplyRdw2(in dchar[] aa, dg2_t dg)
|
||||
{ int result;
|
||||
|
||||
debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length);
|
||||
for (size_t i = aa.length; i != 0; )
|
||||
{ dchar d = aa[--i];
|
||||
wchar w;
|
||||
|
||||
if (d <= 0xFFFF)
|
||||
w = cast(wchar) d;
|
||||
else
|
||||
{
|
||||
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
|
||||
}
|
||||
result = dg(&i, cast(void *)&w);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
assert(k == 4 - i);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(d == 'o'); break;
|
||||
case 1: assert(d == 'l'); break;
|
||||
case 2: assert(d == 'l'); break;
|
||||
case 3: assert(d == 'e'); break;
|
||||
case 4: assert(d == 'h'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
|
||||
s = "a\u1234\U00100456b";
|
||||
i = 0;
|
||||
foreach_reverse(k, wchar d; s)
|
||||
{
|
||||
//printf("i = %d, k = %d, d = %x\n", i, k, d);
|
||||
switch (i)
|
||||
{
|
||||
case 0: assert(k == 3); assert(d == 'b'); break;
|
||||
case 1: assert(k == 2); assert(d == 0xDBC1); break;
|
||||
case 2: assert(k == 2); assert(d == 0xDC56); break;
|
||||
case 3: assert(k == 1); assert(d == 0x1234); break;
|
||||
case 4: assert(k == 0); assert(d == 'a'); break;
|
||||
default: assert(0);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
assert(i == 5);
|
||||
}
|
||||
|
||||
|
||||
837
druntime/src/compiler/ldc/aaA.d
Normal file
837
druntime/src/compiler/ldc/aaA.d
Normal file
@@ -0,0 +1,837 @@
|
||||
//_ aaA.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Implementation of associative arrays.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2008 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
* Modified by Tomas Lindquist Olsen <tomas@famolsen.dk> for use with LDC.
|
||||
*/
|
||||
|
||||
private
|
||||
{
|
||||
version( D_Version2 )
|
||||
{
|
||||
import stdc.stdarg;
|
||||
import stdc.string;
|
||||
}
|
||||
else
|
||||
{
|
||||
import tango.stdc.stdarg;
|
||||
import tango.stdc.string;
|
||||
}
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
// Auto-rehash and pre-allocate - Dave Fladebo
|
||||
|
||||
static size_t[] prime_list = [
|
||||
97UL, 389UL,
|
||||
1_543UL, 6_151UL,
|
||||
24_593UL, 98_317UL,
|
||||
393_241UL, 1_572_869UL,
|
||||
6_291_469UL, 25_165_843UL,
|
||||
100_663_319UL, 402_653_189UL,
|
||||
1_610_612_741UL, 4_294_967_291UL,
|
||||
// 8_589_934_513UL, 17_179_869_143UL
|
||||
];
|
||||
|
||||
struct aaA
|
||||
{
|
||||
aaA *left;
|
||||
aaA *right;
|
||||
hash_t hash;
|
||||
/* key */
|
||||
/* value */
|
||||
}
|
||||
|
||||
struct BB
|
||||
{
|
||||
aaA*[] b;
|
||||
size_t nodes; // total number of aaA nodes
|
||||
TypeInfo keyti; // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
|
||||
}
|
||||
|
||||
/* This is the type actually seen by the programmer, although
|
||||
* it is completely opaque.
|
||||
*/
|
||||
|
||||
// LDC doesn't pass structs in registers so no need to wrap it ...
|
||||
alias BB* AA;
|
||||
|
||||
/**********************************
|
||||
* Align to next pointer boundary, so that
|
||||
* GC won't be faced with misaligned pointers
|
||||
* in value.
|
||||
*/
|
||||
|
||||
size_t aligntsize(size_t tsize)
|
||||
{
|
||||
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
|
||||
}
|
||||
|
||||
extern (C):
|
||||
|
||||
/*************************************************
|
||||
* Invariant for aa.
|
||||
*/
|
||||
|
||||
/+
|
||||
void _aaInvAh(aaA*[] aa)
|
||||
{
|
||||
for (size_t i = 0; i < aa.length; i++)
|
||||
{
|
||||
if (aa[i])
|
||||
_aaInvAh_x(aa[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private int _aaCmpAh_x(aaA *e1, aaA *e2)
|
||||
{ int c;
|
||||
|
||||
c = e1.hash - e2.hash;
|
||||
if (c == 0)
|
||||
{
|
||||
c = e1.key.length - e2.key.length;
|
||||
if (c == 0)
|
||||
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private void _aaInvAh_x(aaA *e)
|
||||
{
|
||||
hash_t key_hash;
|
||||
aaA *e1;
|
||||
aaA *e2;
|
||||
|
||||
key_hash = getHash(e.key);
|
||||
assert(key_hash == e.hash);
|
||||
|
||||
while (1)
|
||||
{ int c;
|
||||
|
||||
e1 = e.left;
|
||||
if (e1)
|
||||
{
|
||||
_aaInvAh_x(e1); // ordinary recursion
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e1, e);
|
||||
assert(c < 0);
|
||||
e1 = e1.right;
|
||||
} while (e1 != null);
|
||||
}
|
||||
|
||||
e2 = e.right;
|
||||
if (e2)
|
||||
{
|
||||
do
|
||||
{
|
||||
c = _aaCmpAh_x(e, e2);
|
||||
assert(c < 0);
|
||||
e2 = e2.left;
|
||||
} while (e2 != null);
|
||||
e = e.right; // tail recursion
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
+/
|
||||
|
||||
/****************************************************
|
||||
* Determine number of entries in associative array.
|
||||
*/
|
||||
|
||||
size_t _aaLen(AA aa)
|
||||
in
|
||||
{
|
||||
//printf("_aaLen()+\n");
|
||||
//_aaInv(aa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
void _aaLen_x(aaA* ex)
|
||||
{
|
||||
auto e = ex;
|
||||
len++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (e.right)
|
||||
_aaLen_x(e.right);
|
||||
e = e.left;
|
||||
if (!e)
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaLen_x(e);
|
||||
}
|
||||
}
|
||||
assert(len == result);
|
||||
|
||||
//printf("_aaLen()-\n");
|
||||
}
|
||||
body
|
||||
{
|
||||
return aa ? aa.nodes : 0;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Add entry for key if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGet(AA* aa_arg, TypeInfo keyti, size_t valuesize, void* pkey)
|
||||
in
|
||||
{
|
||||
assert(aa_arg);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
assert(result);
|
||||
assert(*aa_arg);
|
||||
assert((*aa_arg).b.length);
|
||||
//assert(_aaInAh(*aa, key));
|
||||
}
|
||||
body
|
||||
{
|
||||
//auto pkey = cast(void *)(&valuesize + 1);
|
||||
size_t i;
|
||||
aaA *e;
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
|
||||
if (!*aa_arg)
|
||||
*aa_arg = new BB();
|
||||
auto aa = *aa_arg;
|
||||
aa.keyti = keyti;
|
||||
|
||||
if (!aa.b.length)
|
||||
{
|
||||
alias aaA *pa;
|
||||
auto len = prime_list[0];
|
||||
|
||||
aa.b = new pa[len];
|
||||
}
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % aa.b.length;
|
||||
auto pe = &aa.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
goto Lret;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
size_t size = aaA.sizeof + keysize + valuesize;
|
||||
e = cast(aaA *) gc_calloc(size);
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
|
||||
auto nodes = ++aa.nodes;
|
||||
//printf("length = %d, nodes = %d\n", (*aa).length, nodes);
|
||||
if (nodes > aa.b.length * 4)
|
||||
{
|
||||
_aaRehash(aa_arg,keyti);
|
||||
}
|
||||
|
||||
Lret:
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Get pointer to value in associative array indexed by key.
|
||||
* Returns null if it is not already there.
|
||||
*/
|
||||
|
||||
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void *pkey)
|
||||
{
|
||||
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
|
||||
if (!aa)
|
||||
return null;
|
||||
|
||||
//auto pkey = cast(void *)(&valuesize + 1);
|
||||
auto keysize = aligntsize(keyti.tsize());
|
||||
auto len = aa.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + keysize;
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
return null; // not found, caller will throw exception
|
||||
}
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Determine if key is in aa.
|
||||
* Returns:
|
||||
* null not in aa
|
||||
* !=null in aa, return pointer to value
|
||||
*/
|
||||
|
||||
void* _aaIn(AA aa, TypeInfo keyti, void *pkey)
|
||||
in
|
||||
{
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//assert(result == 0 || result == 1);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
//auto pkey = cast(void *)(&keyti + 1);
|
||||
|
||||
//printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
|
||||
auto len = aa.b.length;
|
||||
|
||||
if (len)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % len;
|
||||
auto e = aa.b[i];
|
||||
while (e !is null)
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
|
||||
e = (c < 0) ? e.left : e.right;
|
||||
}
|
||||
else
|
||||
e = (key_hash < e.hash) ? e.left : e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* Delete key entry in aa[].
|
||||
* If key is not in aa[], do nothing.
|
||||
*/
|
||||
|
||||
void _aaDel(AA aa, TypeInfo keyti, void *pkey)
|
||||
{
|
||||
//auto pkey = cast(void *)(&keyti + 1);
|
||||
aaA *e;
|
||||
|
||||
if (aa && aa.b.length)
|
||||
{
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
size_t i = key_hash % aa.b.length;
|
||||
auto pe = &aa.b[i];
|
||||
while ((e = *pe) !is null) // null means not found
|
||||
{
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
{
|
||||
if (!e.left && !e.right)
|
||||
{
|
||||
*pe = null;
|
||||
}
|
||||
else if (e.left && !e.right)
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
}
|
||||
else if (!e.left && e.right)
|
||||
{
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pe = e.left;
|
||||
e.left = null;
|
||||
do
|
||||
pe = &(*pe).right;
|
||||
while (*pe);
|
||||
*pe = e.right;
|
||||
e.right = null;
|
||||
}
|
||||
|
||||
aa.nodes--;
|
||||
gc_free(e);
|
||||
|
||||
break;
|
||||
}
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of values from aa.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* This means the returned length should be the number of elements
|
||||
*/
|
||||
|
||||
void[] _aaValues(AA aa, size_t keysize, size_t valuesize)
|
||||
in
|
||||
{
|
||||
assert(keysize == aligntsize(keysize));
|
||||
}
|
||||
body
|
||||
{
|
||||
size_t resi;
|
||||
void[] a;
|
||||
|
||||
void _aaValues_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(a.ptr + resi * valuesize,
|
||||
cast(byte*)e + aaA.sizeof + keysize,
|
||||
valuesize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaValues_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
auto len = _aaLen(aa);
|
||||
auto ptr = cast(byte*) gc_malloc(len * valuesize,
|
||||
valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
|
||||
a = ptr[0 .. len];
|
||||
resi = 0;
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaValues_x(e);
|
||||
}
|
||||
assert(resi == a.length);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Rehash an array.
|
||||
*/
|
||||
|
||||
void* _aaRehash(AA* paa, TypeInfo keyti)
|
||||
in
|
||||
{
|
||||
//_aaInvAh(paa);
|
||||
}
|
||||
out (result)
|
||||
{
|
||||
//_aaInvAh(result);
|
||||
}
|
||||
body
|
||||
{
|
||||
BB newb;
|
||||
|
||||
void _aaRehash_x(aaA* olde)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
auto left = olde.left;
|
||||
auto right = olde.right;
|
||||
olde.left = null;
|
||||
olde.right = null;
|
||||
|
||||
aaA *e;
|
||||
|
||||
//printf("rehash %p\n", olde);
|
||||
auto key_hash = olde.hash;
|
||||
size_t i = key_hash % newb.b.length;
|
||||
auto pe = &newb.b[i];
|
||||
while ((e = *pe) !is null)
|
||||
{
|
||||
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
|
||||
assert(e.left != e);
|
||||
assert(e.right != e);
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(olde + 1, e + 1);
|
||||
assert(c != 0);
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
*pe = olde;
|
||||
|
||||
if (right)
|
||||
{
|
||||
if (!left)
|
||||
{ olde = right;
|
||||
continue;
|
||||
}
|
||||
_aaRehash_x(right);
|
||||
}
|
||||
if (!left)
|
||||
break;
|
||||
olde = left;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("Rehash\n");
|
||||
if (*paa)
|
||||
{
|
||||
auto aa = *paa;
|
||||
auto len = _aaLen(aa);
|
||||
if (len)
|
||||
{ size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (len <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
len = prime_list[i];
|
||||
newb.b = new aaA*[len];
|
||||
newb.keyti = keyti;
|
||||
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaRehash_x(e);
|
||||
}
|
||||
|
||||
newb.nodes = (*aa).nodes;
|
||||
}
|
||||
|
||||
**paa = newb;
|
||||
}
|
||||
return *paa;
|
||||
}
|
||||
|
||||
|
||||
/********************************************
|
||||
* Produce array of N byte keys from aa.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* This means the returned length should be the number of elements
|
||||
*/
|
||||
|
||||
void[] _aaKeys(AA aa, size_t keysize)
|
||||
{
|
||||
byte[] res;
|
||||
size_t resi;
|
||||
|
||||
void _aaKeys_x(aaA* e)
|
||||
{
|
||||
do
|
||||
{
|
||||
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
|
||||
resi++;
|
||||
if (e.left)
|
||||
{ if (!e.right)
|
||||
{ e = e.left;
|
||||
continue;
|
||||
}
|
||||
_aaKeys_x(e.left);
|
||||
}
|
||||
e = e.right;
|
||||
} while (e !is null);
|
||||
}
|
||||
|
||||
auto len = _aaLen(aa);
|
||||
if (!len)
|
||||
return null;
|
||||
res = (cast(byte*) gc_malloc(len * keysize,
|
||||
!(aa.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0)) [0 .. len * keysize];
|
||||
resi = 0;
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
_aaKeys_x(e);
|
||||
}
|
||||
assert(resi == len);
|
||||
|
||||
return res.ptr[0 .. len];
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* 'apply' for associative arrays - to support foreach
|
||||
*/
|
||||
|
||||
// dg is D, but _aaApply() is C
|
||||
extern (D) typedef int delegate(void *) dg_t;
|
||||
|
||||
int _aaApply(AA aa, size_t keysize, dg_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// dg is D, but _aaApply2() is C
|
||||
extern (D) typedef int delegate(void *, void *) dg2_t;
|
||||
|
||||
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
|
||||
in
|
||||
{
|
||||
assert(aligntsize(keysize) == keysize);
|
||||
}
|
||||
body
|
||||
{ int result;
|
||||
|
||||
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
|
||||
|
||||
int treewalker(aaA* e)
|
||||
{ int result;
|
||||
|
||||
do
|
||||
{
|
||||
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
|
||||
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
|
||||
if (result)
|
||||
break;
|
||||
if (e.right)
|
||||
{ if (!e.left)
|
||||
{
|
||||
e = e.right;
|
||||
continue;
|
||||
}
|
||||
result = treewalker(e.right);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
e = e.left;
|
||||
} while (e);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
foreach (e; aa.b)
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
result = treewalker(e);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* Construct an associative array of type ti from
|
||||
* length pairs of key/value pairs.
|
||||
*/
|
||||
|
||||
/+
|
||||
|
||||
extern (C)
|
||||
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
|
||||
{
|
||||
auto valuesize = ti.next.tsize(); // value size
|
||||
auto keyti = ti.key;
|
||||
auto keysize = keyti.tsize(); // key size
|
||||
BB* result;
|
||||
|
||||
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
|
||||
//printf("tivalue = %.*s\n", ti.next.classinfo.name);
|
||||
if (length == 0 || valuesize == 0 || keysize == 0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list q;
|
||||
va_start!(size_t)(q, length);
|
||||
|
||||
result = new BB();
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < prime_list.length - 1; i++)
|
||||
{
|
||||
if (length <= prime_list[i])
|
||||
break;
|
||||
}
|
||||
auto len = prime_list[i];
|
||||
result.b = new aaA*[len];
|
||||
|
||||
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
|
||||
|
||||
size_t keytsize = aligntsize(keysize);
|
||||
|
||||
for (size_t j = 0; j < length; j++)
|
||||
{ void* pkey = q;
|
||||
q += keystacksize;
|
||||
void* pvalue = q;
|
||||
q += valuestacksize;
|
||||
aaA* e;
|
||||
|
||||
auto key_hash = keyti.getHash(pkey);
|
||||
//printf("hash = %d\n", key_hash);
|
||||
i = key_hash % len;
|
||||
auto pe = &result.b[i];
|
||||
while (1)
|
||||
{
|
||||
e = *pe;
|
||||
if (!e)
|
||||
{
|
||||
// Not found, create new elem
|
||||
//printf("create new one\n");
|
||||
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
|
||||
memcpy(e + 1, pkey, keysize);
|
||||
e.hash = key_hash;
|
||||
*pe = e;
|
||||
result.nodes++;
|
||||
break;
|
||||
}
|
||||
if (key_hash == e.hash)
|
||||
{
|
||||
auto c = keyti.compare(pkey, e + 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
pe = (c < 0) ? &e.left : &e.right;
|
||||
}
|
||||
else
|
||||
pe = (key_hash < e.hash) ? &e.left : &e.right;
|
||||
}
|
||||
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
|
||||
}
|
||||
|
||||
va_end(q);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+/
|
||||
602
druntime/src/compiler/ldc/adi.d
Normal file
602
druntime/src/compiler/ldc/adi.d
Normal file
@@ -0,0 +1,602 @@
|
||||
//_ adi.d
|
||||
|
||||
/**
|
||||
* Part of the D programming language runtime library.
|
||||
* Dynamic array property support routines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
|
||||
//debug=adi; // uncomment to turn on debugging printf's
|
||||
|
||||
private
|
||||
{
|
||||
version( D_Version2 )
|
||||
{
|
||||
import stdc.stdlib;
|
||||
import stdc.string;
|
||||
}
|
||||
else
|
||||
{
|
||||
import tango.stdc.stdlib;
|
||||
import tango.stdc.string;
|
||||
}
|
||||
import util.utf;
|
||||
|
||||
enum BlkAttr : uint
|
||||
{
|
||||
FINALIZE = 0b0000_0001,
|
||||
NO_SCAN = 0b0000_0010,
|
||||
NO_MOVE = 0b0000_0100,
|
||||
ALL_BITS = 0b1111_1111
|
||||
}
|
||||
|
||||
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
|
||||
extern (C) void gc_free( void* p );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of chars.
|
||||
* Handled separately because embedded multibyte encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) char[] _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
char[6] tmp;
|
||||
char[6] tmplo;
|
||||
char* lo = a.ptr;
|
||||
char* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
|
||||
if (clo <= 0x7F && chi <= 0x7F)
|
||||
{
|
||||
debug(adi) printf("\tascii\n");
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
uint stridelo = UTF8stride[clo];
|
||||
// don't barf on invalid strides, just ignore it
|
||||
if (stridelo == 0xFF)
|
||||
stridelo = 1;
|
||||
|
||||
uint stridehi = 1;
|
||||
while ((chi & 0xC0) == 0x80)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
|
||||
if (stridelo == stridehi)
|
||||
{
|
||||
|
||||
memcpy(tmp.ptr, lo, stridelo);
|
||||
memcpy(lo, hi, stridelo);
|
||||
memcpy(hi, tmp.ptr, stridelo);
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi);
|
||||
memcpy(tmplo.ptr, lo, stridelo);
|
||||
memmove(lo + stridehi, lo + stridelo , cast(size_t)(hi - lo) - stridelo);
|
||||
memcpy(lo, tmp.ptr, stridehi);
|
||||
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
char[] a = "abcd"c;
|
||||
|
||||
char[] r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\u1235\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234\u1235a");
|
||||
|
||||
a = "ab\u1234c";
|
||||
//writefln(a);
|
||||
r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "c\u1234ba");
|
||||
|
||||
a = "\u3026\u2021\u3061\n";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "\n\u3061\u2021\u3026");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Reverse array of wchars.
|
||||
* Handled separately because embedded multiword encodings should not be
|
||||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) wchar[] _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
wchar[2] tmp;
|
||||
wchar* lo = a.ptr;
|
||||
wchar* hi = &a[length - 1];
|
||||
|
||||
while (lo < hi)
|
||||
{ auto clo = *lo;
|
||||
auto chi = *hi;
|
||||
|
||||
if ((clo < 0xD800 || clo > 0xDFFF) &&
|
||||
(chi < 0xD800 || chi > 0xDFFF))
|
||||
{
|
||||
*lo = chi;
|
||||
*hi = clo;
|
||||
lo++;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
|
||||
|
||||
int stridehi = 1;
|
||||
if (chi >= 0xDC00 && chi <= 0xDFFF)
|
||||
{
|
||||
chi = *--hi;
|
||||
stridehi++;
|
||||
assert(hi >= lo);
|
||||
}
|
||||
if (lo == hi)
|
||||
break;
|
||||
|
||||
if (stridelo == stridehi)
|
||||
{ int stmp;
|
||||
|
||||
assert(stridelo == 2);
|
||||
assert(stmp.sizeof == 2 * (*lo).sizeof);
|
||||
stmp = *cast(int*)lo;
|
||||
*cast(int*)lo = *cast(int*)hi;
|
||||
*cast(int*)hi = stmp;
|
||||
lo += stridelo;
|
||||
hi--;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Shift the whole array. This is woefully inefficient
|
||||
*/
|
||||
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
|
||||
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
|
||||
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
|
||||
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
|
||||
|
||||
lo += stridehi;
|
||||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wchar[] a = "abcd";
|
||||
wchar[] r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
||||
a = "a\U00012356\U00012346c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012346\U00012356a");
|
||||
|
||||
a = "ab\U00012345c";
|
||||
r = a.dup.reverse;
|
||||
assert(r == "c\U00012345ba");
|
||||
}
|
||||
|
||||
|
||||
/**********************************************
|
||||
* Support for array.reverse property.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* Given and returned length are number of elements
|
||||
*/
|
||||
|
||||
extern (C) void[] _adReverse(void[] a, size_t szelem)
|
||||
out (result)
|
||||
{
|
||||
assert(result.ptr is a.ptr);
|
||||
}
|
||||
body
|
||||
{
|
||||
if (a.length >= 2)
|
||||
{
|
||||
byte* tmp;
|
||||
byte[16] buffer;
|
||||
|
||||
void* lo = a.ptr;
|
||||
void* hi = a.ptr + (a.length - 1) * szelem;
|
||||
|
||||
tmp = buffer.ptr;
|
||||
if (szelem > 16)
|
||||
{
|
||||
//version (Win32)
|
||||
//tmp = cast(byte*) alloca(szelem);
|
||||
//else
|
||||
tmp = cast(byte*) gc_malloc(szelem);
|
||||
}
|
||||
|
||||
for (; lo < hi; lo += szelem, hi -= szelem)
|
||||
{
|
||||
memcpy(tmp, lo, szelem);
|
||||
memcpy(lo, hi, szelem);
|
||||
memcpy(hi, tmp, szelem);
|
||||
}
|
||||
|
||||
version (Win32)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (szelem > 16)
|
||||
// BUG: bad code is generate for delete pointer, tries
|
||||
// to call delclass.
|
||||
//gc_free(tmp);
|
||||
}
|
||||
}
|
||||
return a.ptr[0 .. a.length];
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.reverse.unittest\n");
|
||||
|
||||
int[] a = new int[5];
|
||||
int[] b;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
a[i] = i;
|
||||
b = a.reverse;
|
||||
assert(b is a);
|
||||
for (i = 0; i < 5; i++)
|
||||
assert(a[i] == 4 - i);
|
||||
|
||||
struct X20
|
||||
{ // More than 16 bytes in size
|
||||
int a;
|
||||
int b, c, d, e;
|
||||
}
|
||||
|
||||
X20[] c = new X20[5];
|
||||
X20[] d;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{ c[i].a = i;
|
||||
c[i].e = 10;
|
||||
}
|
||||
d = c.reverse;
|
||||
assert(d is c);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
assert(c[i].a == 4 - i);
|
||||
assert(c[i].e == 10);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) char[] _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ char[4] buf;
|
||||
auto t = toUTF8(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) wchar[] _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
dstring da = toUTF32(a);
|
||||
da.sort;
|
||||
size_t i = 0;
|
||||
foreach (dchar d; da)
|
||||
{ wchar[2] buf;
|
||||
auto t = toUTF16(buf, d);
|
||||
a[i .. i + t.length] = t[];
|
||||
i += t.length;
|
||||
}
|
||||
delete da;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array equality test.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* Given lengths are number of elements
|
||||
*/
|
||||
|
||||
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)
|
||||
return 0; // not equal
|
||||
else if (a1.ptr == a2.ptr)
|
||||
return 1; // equal
|
||||
|
||||
// let typeinfo decide
|
||||
return ti.equals(&a1, &a2);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
char[] a = "hello"c;
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
assert(a != "betty");
|
||||
assert(a == "hello");
|
||||
assert(a != "hxxxx");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* Given lengths are number of elements
|
||||
*/
|
||||
|
||||
extern (C) int _adCmp(void[] a1, void[] a2, TypeInfo ti)
|
||||
{
|
||||
debug(adi) printf("adCmp()\n");
|
||||
|
||||
if (a1.ptr == a2.ptr &&
|
||||
a1.length == a2.length)
|
||||
return 0;
|
||||
|
||||
auto len = a1.length;
|
||||
if (a2.length < len)
|
||||
len = a2.length;
|
||||
|
||||
// let typeinfo decide
|
||||
return ti.compare(&a1, &a2);
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
char[] a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* Support for array compare test.
|
||||
* The actual type is painted on the return value by the frontend
|
||||
* Given lengths are number of elements
|
||||
*/
|
||||
|
||||
extern (C) int _adCmpChar(void[] a1, void[] a2)
|
||||
{
|
||||
version(D_InlineAsm_X86)
|
||||
{
|
||||
//version = Asm86;
|
||||
}
|
||||
version (Asm86)
|
||||
{
|
||||
asm
|
||||
{ naked ;
|
||||
|
||||
push EDI ;
|
||||
push ESI ;
|
||||
|
||||
mov ESI,a1+4[4+ESP] ;
|
||||
mov EDI,a2+4[4+ESP] ;
|
||||
|
||||
mov ECX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
cmp ECX,EDX ;
|
||||
jb GotLength ;
|
||||
|
||||
mov ECX,EDX ;
|
||||
|
||||
GotLength:
|
||||
cmp ECX,4 ;
|
||||
jb DoBytes ;
|
||||
|
||||
// Do alignment if neither is dword aligned
|
||||
test ESI,3 ;
|
||||
jz Aligned ;
|
||||
|
||||
test EDI,3 ;
|
||||
jz Aligned ;
|
||||
DoAlign:
|
||||
mov AL,[ESI] ; //align ESI to dword bounds
|
||||
mov DL,[EDI] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
inc ESI ;
|
||||
inc EDI ;
|
||||
|
||||
test ESI,3 ;
|
||||
|
||||
lea ECX,[ECX-1] ;
|
||||
jnz DoAlign ;
|
||||
Aligned:
|
||||
mov EAX,ECX ;
|
||||
|
||||
// do multiple of 4 bytes at a time
|
||||
|
||||
shr ECX,2 ;
|
||||
jz TryOdd ;
|
||||
|
||||
repe ;
|
||||
cmpsd ;
|
||||
|
||||
jnz UnequalQuad ;
|
||||
|
||||
TryOdd:
|
||||
mov ECX,EAX ;
|
||||
DoBytes:
|
||||
// if still equal and not end of string, do up to 3 bytes slightly
|
||||
// slower.
|
||||
|
||||
and ECX,3 ;
|
||||
jz Equal ;
|
||||
|
||||
repe ;
|
||||
cmpsb ;
|
||||
|
||||
jnz Unequal ;
|
||||
Equal:
|
||||
mov EAX,a1[4+ESP] ;
|
||||
mov EDX,a2[4+ESP] ;
|
||||
|
||||
sub EAX,EDX ;
|
||||
pop ESI ;
|
||||
|
||||
pop EDI ;
|
||||
ret ;
|
||||
|
||||
UnequalQuad:
|
||||
mov EDX,[EDI-4] ;
|
||||
mov EAX,[ESI-4] ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
jnz Unequal ;
|
||||
|
||||
shr EAX,16 ;
|
||||
|
||||
shr EDX,16 ;
|
||||
|
||||
cmp AL,DL ;
|
||||
jnz Unequal ;
|
||||
|
||||
cmp AH,DH ;
|
||||
Unequal:
|
||||
sbb EAX,EAX ;
|
||||
pop ESI ;
|
||||
|
||||
or EAX,1 ;
|
||||
pop EDI ;
|
||||
|
||||
ret ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
int c;
|
||||
|
||||
debug(adi) printf("adCmpChar()\n");
|
||||
len = cast(int)a1.length;
|
||||
if (a2.length < len)
|
||||
len = cast(int)a2.length;
|
||||
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
|
||||
if (!c)
|
||||
c = cast(int)a1.length - cast(int)a2.length;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
char[] a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
assert(a < "helloo");
|
||||
assert(a <= "helloo");
|
||||
assert(a > "betty");
|
||||
assert(a >= "betty");
|
||||
assert(a == "hello");
|
||||
assert(a <= "hello");
|
||||
assert(a >= "hello");
|
||||
}
|
||||
158
druntime/src/compiler/ldc/arrayInit.d
Normal file
158
druntime/src/compiler/ldc/arrayInit.d
Normal file
@@ -0,0 +1,158 @@
|
||||
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_i1(bool* a, size_t n, bool v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i8(ubyte* a, size_t n, ubyte v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i16(ushort* a, size_t n, ushort v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i32(uint* a, size_t n, uint v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_i64(ulong* a, size_t n, ulong v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_float(float* a, size_t n, float v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_double(double* a, size_t n, double v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_real(real* a, size_t n, real v)
|
||||
{
|
||||
auto p = a;
|
||||
auto end = a+n;
|
||||
while (p !is end)
|
||||
*p++ = v;
|
||||
}
|
||||
|
||||
void _d_array_init_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;
|
||||
}
|
||||
196
druntime/src/compiler/ldc/cast.d
Normal file
196
druntime/src/compiler/ldc/cast.d
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
|
||||
* Written by Walter Bright
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, in both source and binary form, subject to the following
|
||||
* restrictions:
|
||||
*
|
||||
* o The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* o Altered source versions must be plainly marked as such, and must not
|
||||
* be misrepresented as being the original software.
|
||||
* o This notice may not be removed or altered from any source
|
||||
* distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
||||
*/
|
||||
|
||||
extern (C):
|
||||
|
||||
//debug = PRINTF;
|
||||
debug(PRINTF) int printf(char*, ...);
|
||||
|
||||
/******************************************
|
||||
* Given a pointer:
|
||||
* If it is an Object, return that Object.
|
||||
* If it is an interface, return the Object implementing the interface.
|
||||
* If it is null, return null.
|
||||
* Else, undefined crash
|
||||
*/
|
||||
|
||||
Object _d_toObject(void* p)
|
||||
{ Object o;
|
||||
debug(PRINTF) printf("toObject(%p)\n", p);
|
||||
if (p)
|
||||
{
|
||||
o = cast(Object)p;
|
||||
debug(PRINTF) printf("o = %p\n", o);
|
||||
debug(PRINTF) printf("o.vtbl = %p\n", *cast(void**)p);
|
||||
ClassInfo oc = o.classinfo;
|
||||
debug(PRINTF) printf("oc = %p\n", oc);
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
debug(PRINTF) printf("pi = %p\n", pi);
|
||||
|
||||
/* Interface.offset lines up with ClassInfo.name.ptr,
|
||||
* so we rely on pointers never being less than 64K,
|
||||
* and interface vtable offsets never being greater.
|
||||
*/
|
||||
if (pi.offset < 0x10000)
|
||||
{
|
||||
debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
}
|
||||
}
|
||||
debug(PRINTF) printf("toObject = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Attempts to cast Object o to class c.
|
||||
* Returns o if successful, null if not.
|
||||
*/
|
||||
|
||||
Object _d_interface_cast(void* p, ClassInfo c)
|
||||
{ Object o;
|
||||
|
||||
debug(PRINTF) printf("_d_interface_cast(p = %p, c = '%.*s')\n", p, c.name.length, c.name.ptr);
|
||||
if (p)
|
||||
{
|
||||
Interface *pi = **cast(Interface ***)p;
|
||||
|
||||
debug(PRINTF) printf("\tpi.offset = %d\n", pi.offset);
|
||||
o = cast(Object)(p - pi.offset);
|
||||
return _d_dynamic_cast(o, c);
|
||||
}
|
||||
debug(PRINTF) printf("_d_interface_cast = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
Object _d_dynamic_cast(Object o, ClassInfo c)
|
||||
{ ClassInfo oc;
|
||||
size_t offset = 0;
|
||||
|
||||
debug(PRINTF) printf("_d_dynamic_cast(o = %p, c = '%.*s')\n", o, c.name.length, c.name.ptr);
|
||||
|
||||
if (o)
|
||||
{
|
||||
oc = o.classinfo;
|
||||
if (_d_isbaseof2(oc, c, offset))
|
||||
{
|
||||
debug(PRINTF) printf("\toffset = %d\n", offset);
|
||||
o = cast(Object)(cast(void*)o + offset);
|
||||
}
|
||||
else
|
||||
o = null;
|
||||
}
|
||||
//printf("\tresult = %p\n", o);
|
||||
debug(PRINTF) printf("_d_dynamic_cast = %p\n", o);
|
||||
return o;
|
||||
}
|
||||
|
||||
int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset)
|
||||
{ int i;
|
||||
|
||||
debug(PRINTF) printf("_d_isbaseof2(%.*s, %.*s, %ul)\n", oc.name.length, oc.name.ptr, c.name.length, c.name.ptr, offset);
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
debug(PRINTF) printf("oc.interfaces.length = %ul\n", oc.interfaces.length);
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
debug(PRINTF) printf("checking %.*s\n", ic.name.length, ic.name.ptr);
|
||||
if (ic is c)
|
||||
{ offset = cast(size_t)oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (_d_isbaseof2(ic, c, offset))
|
||||
{ offset = cast(size_t)oc.interfaces[i].offset;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _d_isbaseof(ClassInfo oc, ClassInfo c)
|
||||
{ int i;
|
||||
|
||||
if (oc is c)
|
||||
return 1;
|
||||
do
|
||||
{
|
||||
if (oc.base is c)
|
||||
return 1;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo ic;
|
||||
|
||||
ic = oc.interfaces[i].classinfo;
|
||||
if (ic is c || _d_isbaseof(ic, c))
|
||||
return 1;
|
||||
}
|
||||
oc = oc.base;
|
||||
} while (oc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* Find the vtbl[] associated with Interface ic.
|
||||
*/
|
||||
|
||||
void *_d_interface_vtbl(ClassInfo ic, Object o)
|
||||
{ int i;
|
||||
ClassInfo oc;
|
||||
|
||||
//printf("__d_interface_vtbl(o = %p, ic = %p)\n", o, ic);
|
||||
|
||||
assert(o);
|
||||
|
||||
oc = o.classinfo;
|
||||
for (i = 0; i < oc.interfaces.length; i++)
|
||||
{
|
||||
ClassInfo oic;
|
||||
|
||||
oic = oc.interfaces[i].classinfo;
|
||||
if (oic is ic)
|
||||
{
|
||||
return cast(void *)oc.interfaces[i].vtbl;
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
164
druntime/src/compiler/ldc/critical.c
Normal file
164
druntime/src/compiler/ldc/critical.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Placed into the Public Domain
|
||||
* written by Walter Bright, Digital Mars
|
||||
* www.digitalmars.com
|
||||
*/
|
||||
|
||||
/* ================================= Win32 ============================ */
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
CRITICAL_SECTION cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static volatile int inited;
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs->next)
|
||||
{
|
||||
EnterCriticalSection(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
InitializeCriticalSection(&dcs->cs);
|
||||
}
|
||||
LeaveCriticalSection(&critical_section.cs);
|
||||
}
|
||||
EnterCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
LeaveCriticalSection(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!inited)
|
||||
{ InitializeCriticalSection(&critical_section.cs);
|
||||
dcs_list = &critical_section;
|
||||
inited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (inited)
|
||||
{ inited = 0;
|
||||
while (dcs_list)
|
||||
{
|
||||
DeleteCriticalSection(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ================================= linux ============================ */
|
||||
|
||||
#if linux || __APPLE__ || __FreeBSD__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#if !linux
|
||||
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
|
||||
#endif
|
||||
|
||||
/******************************************
|
||||
* Enter/exit critical section.
|
||||
*/
|
||||
|
||||
/* We don't initialize critical sections unless we actually need them.
|
||||
* So keep a linked list of the ones we do use, and in the static destructor
|
||||
* code, walk the list and release them.
|
||||
*/
|
||||
|
||||
typedef struct D_CRITICAL_SECTION
|
||||
{
|
||||
struct D_CRITICAL_SECTION *next;
|
||||
pthread_mutex_t cs;
|
||||
} D_CRITICAL_SECTION;
|
||||
|
||||
static D_CRITICAL_SECTION *dcs_list;
|
||||
static D_CRITICAL_SECTION critical_section;
|
||||
static pthread_mutexattr_t _criticals_attr;
|
||||
|
||||
void _STI_critical_init(void);
|
||||
void _STD_critical_term(void);
|
||||
|
||||
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ _STI_critical_init();
|
||||
atexit(_STD_critical_term);
|
||||
}
|
||||
//printf("_d_criticalenter(dcs = x%x)\n", dcs);
|
||||
if (!dcs->next)
|
||||
{
|
||||
pthread_mutex_lock(&critical_section.cs);
|
||||
if (!dcs->next) // if, in the meantime, another thread didn't set it
|
||||
{
|
||||
dcs->next = dcs_list;
|
||||
dcs_list = dcs;
|
||||
pthread_mutex_init(&dcs->cs, &_criticals_attr);
|
||||
}
|
||||
pthread_mutex_unlock(&critical_section.cs);
|
||||
}
|
||||
pthread_mutex_lock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
|
||||
{
|
||||
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
|
||||
pthread_mutex_unlock(&dcs->cs);
|
||||
}
|
||||
|
||||
void _STI_critical_init()
|
||||
{
|
||||
if (!dcs_list)
|
||||
{ //printf("_STI_critical_init()\n");
|
||||
pthread_mutexattr_init(&_criticals_attr);
|
||||
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
|
||||
// The global critical section doesn't need to be recursive
|
||||
pthread_mutex_init(&critical_section.cs, 0);
|
||||
dcs_list = &critical_section;
|
||||
}
|
||||
}
|
||||
|
||||
void _STD_critical_term()
|
||||
{
|
||||
if (dcs_list)
|
||||
{ //printf("_STI_critical_term()\n");
|
||||
while (dcs_list)
|
||||
{
|
||||
//printf("\tlooping... %x\n", dcs_list);
|
||||
pthread_mutex_destroy(&dcs_list->cs);
|
||||
dcs_list = dcs_list->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user