Removed tango from the repository and instead added a runtime dir with the files needed to patch and build tango from svn.

Reworked the LLVMDC specific pragmas.
This commit is contained in:
Tomas Lindquist Olsen
2008-08-01 00:32:06 +02:00
parent 8f14ece3af
commit 07cfb67178
534 changed files with 1502 additions and 258956 deletions

11
runtime/README Normal file
View File

@@ -0,0 +1,11 @@
1) Do a checkout of tango trunk in the llvmdc root dir (along dmd, gen, runtime etc).
* svn co http://svn.dsource.org/projects/tango/trunk ../tango
2) Patch the runtime
* sh patch-tango.sh
3) Compile the runtime
* sh build.sh

17
runtime/build.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
# I'm no good bash scripter ...
# copy imports
cp -u internal/llvmdc/bitmanip.d ../import/llvmdc/bitmanip.di
cp -u internal/llvmdc/vararg.d ../import/llvmdc/vararg.di
# make the runtime
cp -Ru lib ../tango
cd ../tango/lib
make -f llvmdc-posix.mak clean
make -f llvmdc-posix.mak
# install the runtime
rm -f ../../lib/libtango-base-llvmdc-native.a
cp -s `pwd`/libtango-base-llvmdc-native.a ../../lib

406
runtime/internal/aApply.d Normal file
View File

@@ -0,0 +1,406 @@
/**
* Part of the D programming language runtime library.
*/
/*
* Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
/* This code handles decoding UTF strings for foreach loops.
* There are 6 combinations of conversions between char, wchar,
* and dchar, and 2 of each of those.
*/
private import util.utf;
/**********************************************
*/
// dg is D, but _aApplycd() is C
extern (D) typedef int delegate(void *) dg_t;
extern (C) int _aApplycd1(char[] aa, dg_t dg)
{ int result;
size_t i;
size_t len = aa.length;
debug(apply) printf("_aApplycd1(), len = %d\n", len);
for (i = 0; i < len; )
{ dchar d;
d = aa[i];
if (d & 0x80)
d = decode(aa, i);
else
i++;
result = dg(cast(void *)&d);
if (result)
break;
}
return result;
}
extern (C) int _aApplywd1(wchar[] aa, dg_t dg)
{ int result;
size_t i;
size_t len = aa.length;
debug(apply) printf("_aApplywd1(), len = %d\n", len);
for (i = 0; i < len; )
{ dchar d;
d = aa[i];
if (d & ~0x7F)
d = decode(aa, i);
else
i++;
result = dg(cast(void *)&d);
if (result)
break;
}
return result;
}
extern (C) int _aApplycw1(char[] aa, dg_t dg)
{ int result;
size_t i;
size_t len = aa.length;
debug(apply) printf("_aApplycw1(), len = %d\n", len);
for (i = 0; i < len; )
{ dchar d;
wchar w;
w = aa[i];
if (w & 0x80)
{ d = decode(aa, i);
if (d <= 0xFFFF)
w = cast(wchar) d;
else
{
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
result = dg(cast(void *)&w);
if (result)
break;
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
}
}
else
i++;
result = dg(cast(void *)&w);
if (result)
break;
}
return result;
}
extern (C) int _aApplywc1(wchar[] aa, dg_t dg)
{ int result;
size_t i;
size_t len = aa.length;
debug(apply) printf("_aApplywc1(), len = %d\n", len);
for (i = 0; i < len; )
{ dchar d;
wchar w;
char c;
w = aa[i];
if (w & ~0x7F)
{
char[4] buf;
d = decode(aa, i);
auto b = toUTF8(buf, d);
foreach (char c2; b)
{
result = dg(cast(void *)&c2);
if (result)
return result;
}
continue;
}
else
{ c = cast(char)w;
i++;
}
result = dg(cast(void *)&c);
if (result)
break;
}
return result;
}
extern (C) int _aApplydc1(dchar[] aa, dg_t dg)
{ int result;
debug(apply) printf("_aApplydc1(), len = %d\n", aa.length);
foreach (dchar d; aa)
{
char c;
if (d & ~0x7F)
{
char[4] buf;
auto b = toUTF8(buf, d);
foreach (char c2; b)
{
result = dg(cast(void *)&c2);
if (result)
return result;
}
continue;
}
else
{
c = cast(char)d;
}
result = dg(cast(void *)&c);
if (result)
break;
}
return result;
}
extern (C) int _aApplydw1(dchar[] aa, dg_t dg)
{ int result;
debug(apply) printf("_aApplydw1(), len = %d\n", aa.length);
foreach (dchar d; aa)
{
wchar w;
if (d <= 0xFFFF)
w = cast(wchar) d;
else
{
w = cast(wchar)((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
result = dg(cast(void *)&w);
if (result)
break;
w = cast(wchar)(((d - 0x10000) & 0x3FF) + 0xDC00);
}
result = dg(cast(void *)&w);
if (result)
break;
}
return result;
}
/****************************************************************************/
// dg is D, but _aApplycd2() is C
extern (D) typedef int delegate(void *, void *) dg2_t;
extern (C) int _aApplycd2(char[] aa, dg2_t dg)
{ int result;
size_t i;
size_t n;
size_t len = aa.length;
debug(apply) printf("_aApplycd2(), len = %d\n", len);
for (i = 0; i < len; i += n)
{ dchar d;
d = aa[i];
if (d & 0x80)
{
n = i;
d = decode(aa, n);
n -= i;
}
else
n = 1;
result = dg(&i, cast(void *)&d);
if (result)
break;
}
return result;
}
extern (C) int _aApplywd2(wchar[] aa, dg2_t dg)
{ int result;
size_t i;
size_t n;
size_t len = aa.length;
debug(apply) printf("_aApplywd2(), len = %d\n", len);
for (i = 0; i < len; i += n)
{ dchar d;
d = aa[i];
if (d & ~0x7F)
{
n = i;
d = decode(aa, n);
n -= i;
}
else
n = 1;
result = dg(&i, cast(void *)&d);
if (result)
break;
}
return result;
}
extern (C) int _aApplycw2(char[] aa, dg2_t dg)
{ int result;
size_t i;
size_t n;
size_t len = aa.length;
debug(apply) printf("_aApplycw2(), len = %d\n", len);
for (i = 0; i < len; i += n)
{ dchar d;
wchar w;
w = aa[i];
if (w & 0x80)
{ n = i;
d = decode(aa, n);
n -= i;
if (d <= 0xFFFF)
w = cast(wchar) d;
else
{
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
result = dg(&i, cast(void *)&w);
if (result)
break;
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
}
}
else
n = 1;
result = dg(&i, cast(void *)&w);
if (result)
break;
}
return result;
}
extern (C) int _aApplywc2(wchar[] aa, dg2_t dg)
{ int result;
size_t i;
size_t n;
size_t len = aa.length;
debug(apply) printf("_aApplywc2(), len = %d\n", len);
for (i = 0; i < len; i += n)
{ dchar d;
wchar w;
char c;
w = aa[i];
if (w & ~0x7F)
{
char[4] buf;
n = i;
d = decode(aa, n);
n -= i;
auto b = toUTF8(buf, d);
foreach (char c2; b)
{
result = dg(&i, cast(void *)&c2);
if (result)
return result;
}
continue;
}
else
{ c = cast(char)w;
n = 1;
}
result = dg(&i, cast(void *)&c);
if (result)
break;
}
return result;
}
extern (C) int _aApplydc2(dchar[] aa, dg2_t dg)
{ int result;
size_t i;
size_t len = aa.length;
debug(apply) printf("_aApplydc2(), len = %d\n", len);
for (i = 0; i < len; i++)
{ dchar d;
char c;
d = aa[i];
if (d & ~0x7F)
{
char[4] buf;
auto b = toUTF8(buf, d);
foreach (char c2; b)
{
result = dg(&i, cast(void *)&c2);
if (result)
return result;
}
continue;
}
else
{ c = cast(char)d;
}
result = dg(&i, cast(void *)&c);
if (result)
break;
}
return result;
}
extern (C) int _aApplydw2(dchar[] aa, dg2_t dg)
{ int result;
debug(apply) printf("_aApplydw2(), len = %d\n", aa.length);
foreach (size_t i, dchar d; aa)
{
wchar w;
auto j = i;
if (d <= 0xFFFF)
w = cast(wchar) d;
else
{
w = cast(wchar) ((((d - 0x10000) >> 10) & 0x3FF) + 0xD800);
result = dg(&j, cast(void *)&w);
if (result)
break;
w = cast(wchar) (((d - 0x10000) & 0x3FF) + 0xDC00);
}
result = dg(&j, cast(void *)&w);
if (result)
break;
}
return result;
}

975
runtime/internal/aApplyR.d Normal file
View 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");
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);
}

832
runtime/internal/aaA.d Normal file
View File

@@ -0,0 +1,832 @@
//_ aaA.d
/**
* Part of the D programming language runtime library.
* Implementation of associative arrays.
*/
/*
* Copyright (C) 2000-2008 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
* Modified by Tomas Lindquist Olsen <tomas@famolsen.dk> for use with LLVMDC.
*/
private
{
import tango.stdc.stdarg;
import tango.stdc.string;
enum BlkAttr : uint
{
FINALIZE = 0b0000_0001,
NO_SCAN = 0b0000_0010,
NO_MOVE = 0b0000_0100,
ALL_BITS = 0b1111_1111
}
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
extern (C) void gc_free( void* p );
}
// Auto-rehash and pre-allocate - Dave Fladebo
static size_t[] prime_list = [
97UL, 389UL,
1_543UL, 6_151UL,
24_593UL, 98_317UL,
393_241UL, 1_572_869UL,
6_291_469UL, 25_165_843UL,
100_663_319UL, 402_653_189UL,
1_610_612_741UL, 4_294_967_291UL,
// 8_589_934_513UL, 17_179_869_143UL
];
// This is the type of the return value for dynamic arrays.
struct Array
{
size_t length;
void* ptr;
}
struct aaA
{
aaA *left;
aaA *right;
hash_t hash;
/* key */
/* value */
}
struct BB
{
aaA*[] b;
size_t nodes; // total number of aaA nodes
TypeInfo keyti; // TODO: replace this with TypeInfo_AssociativeArray when available in _aaGet()
}
/* This is the type actually seen by the programmer, although
* it is completely opaque.
*/
// LLVMDC doesn't pass structs in registers so no need to wrap it ...
alias BB* AA;
/**********************************
* Align to next pointer boundary, so that
* GC won't be faced with misaligned pointers
* in value.
*/
size_t aligntsize(size_t tsize)
{
// Is pointer alignment on the x64 4 bytes or 8?
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
}
extern (C):
/*************************************************
* Invariant for aa.
*/
/+
void _aaInvAh(aaA*[] aa)
{
for (size_t i = 0; i < aa.length; i++)
{
if (aa[i])
_aaInvAh_x(aa[i]);
}
}
private int _aaCmpAh_x(aaA *e1, aaA *e2)
{ int c;
c = e1.hash - e2.hash;
if (c == 0)
{
c = e1.key.length - e2.key.length;
if (c == 0)
c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
}
return c;
}
private void _aaInvAh_x(aaA *e)
{
hash_t key_hash;
aaA *e1;
aaA *e2;
key_hash = getHash(e.key);
assert(key_hash == e.hash);
while (1)
{ int c;
e1 = e.left;
if (e1)
{
_aaInvAh_x(e1); // ordinary recursion
do
{
c = _aaCmpAh_x(e1, e);
assert(c < 0);
e1 = e1.right;
} while (e1 != null);
}
e2 = e.right;
if (e2)
{
do
{
c = _aaCmpAh_x(e, e2);
assert(c < 0);
e2 = e2.left;
} while (e2 != null);
e = e.right; // tail recursion
}
else
break;
}
}
+/
/****************************************************
* Determine number of entries in associative array.
*/
size_t _aaLen(AA aa)
in
{
//printf("_aaLen()+\n");
//_aaInv(aa);
}
out (result)
{
size_t len = 0;
void _aaLen_x(aaA* ex)
{
auto e = ex;
len++;
while (1)
{
if (e.right)
_aaLen_x(e.right);
e = e.left;
if (!e)
break;
len++;
}
}
if (aa)
{
foreach (e; aa.b)
{
if (e)
_aaLen_x(e);
}
}
assert(len == result);
//printf("_aaLen()-\n");
}
body
{
return aa ? aa.nodes : 0;
}
/*************************************************
* Get pointer to value in associative array indexed by key.
* Add entry for key if it is not already there.
*/
void* _aaGet(AA* aa_arg, TypeInfo keyti, size_t valuesize, void* pkey)
in
{
assert(aa_arg);
}
out (result)
{
assert(result);
assert(*aa_arg);
assert((*aa_arg).b.length);
//assert(_aaInAh(*aa, key));
}
body
{
//auto pkey = cast(void *)(&valuesize + 1);
size_t i;
aaA *e;
auto keysize = aligntsize(keyti.tsize());
if (!*aa_arg)
*aa_arg = new BB();
auto aa = *aa_arg;
aa.keyti = keyti;
if (!aa.b.length)
{
alias aaA *pa;
auto len = prime_list[0];
aa.b = new pa[len];
}
auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash);
i = key_hash % aa.b.length;
auto pe = &aa.b[i];
while ((e = *pe) !is null)
{
if (key_hash == e.hash)
{
auto c = keyti.compare(pkey, e + 1);
if (c == 0)
goto Lret;
pe = (c < 0) ? &e.left : &e.right;
}
else
pe = (key_hash < e.hash) ? &e.left : &e.right;
}
// Not found, create new elem
//printf("create new one\n");
size_t size = aaA.sizeof + keysize + valuesize;
e = cast(aaA *) gc_calloc(size);
memcpy(e + 1, pkey, keysize);
e.hash = key_hash;
*pe = e;
auto nodes = ++aa.nodes;
//printf("length = %d, nodes = %d\n", (*aa).length, nodes);
if (nodes > aa.b.length * 4)
{
_aaRehash(aa_arg,keyti);
}
Lret:
return cast(void *)(e + 1) + keysize;
}
/*************************************************
* Get pointer to value in associative array indexed by key.
* Returns null if it is not already there.
*/
void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, void *pkey)
{
//printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
if (!aa)
return null;
//auto pkey = cast(void *)(&valuesize + 1);
auto keysize = aligntsize(keyti.tsize());
auto len = aa.b.length;
if (len)
{
auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash);
size_t i = key_hash % len;
auto e = aa.b[i];
while (e !is null)
{
if (key_hash == e.hash)
{
auto c = keyti.compare(pkey, e + 1);
if (c == 0)
return cast(void *)(e + 1) + keysize;
e = (c < 0) ? e.left : e.right;
}
else
e = (key_hash < e.hash) ? e.left : e.right;
}
}
return null; // not found, caller will throw exception
}
/*************************************************
* Determine if key is in aa.
* Returns:
* null not in aa
* !=null in aa, return pointer to value
*/
void* _aaIn(AA aa, TypeInfo keyti, void *pkey)
in
{
}
out (result)
{
//assert(result == 0 || result == 1);
}
body
{
if (aa)
{
//auto pkey = cast(void *)(&keyti + 1);
//printf("_aaIn(), .length = %d, .ptr = %x\n", aa.length, cast(uint)aa.ptr);
auto len = aa.b.length;
if (len)
{
auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash);
size_t i = key_hash % len;
auto e = aa.b[i];
while (e !is null)
{
if (key_hash == e.hash)
{
auto c = keyti.compare(pkey, e + 1);
if (c == 0)
return cast(void *)(e + 1) + aligntsize(keyti.tsize());
e = (c < 0) ? e.left : e.right;
}
else
e = (key_hash < e.hash) ? e.left : e.right;
}
}
}
// Not found
return null;
}
/*************************************************
* Delete key entry in aa[].
* If key is not in aa[], do nothing.
*/
void _aaDel(AA aa, TypeInfo keyti, void *pkey)
{
//auto pkey = cast(void *)(&keyti + 1);
aaA *e;
if (aa && aa.b.length)
{
auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash);
size_t i = key_hash % aa.b.length;
auto pe = &aa.b[i];
while ((e = *pe) !is null) // null means not found
{
if (key_hash == e.hash)
{
auto c = keyti.compare(pkey, e + 1);
if (c == 0)
{
if (!e.left && !e.right)
{
*pe = null;
}
else if (e.left && !e.right)
{
*pe = e.left;
e.left = null;
}
else if (!e.left && e.right)
{
*pe = e.right;
e.right = null;
}
else
{
*pe = e.left;
e.left = null;
do
pe = &(*pe).right;
while (*pe);
*pe = e.right;
e.right = null;
}
aa.nodes--;
gc_free(e);
break;
}
pe = (c < 0) ? &e.left : &e.right;
}
else
pe = (key_hash < e.hash) ? &e.left : &e.right;
}
}
}
/********************************************
* Produce array of values from aa.
*/
Array _aaValues(AA aa, size_t keysize, size_t valuesize)
in
{
assert(keysize == aligntsize(keysize));
}
body
{
size_t resi;
Array a;
void _aaValues_x(aaA* e)
{
do
{
memcpy(a.ptr + resi * valuesize,
cast(byte*)e + aaA.sizeof + keysize,
valuesize);
resi++;
if (e.left)
{ if (!e.right)
{ e = e.left;
continue;
}
_aaValues_x(e.left);
}
e = e.right;
} while (e !is null);
}
if (aa)
{
a.length = _aaLen(aa);
a.ptr = cast(byte*) gc_malloc(a.length * valuesize,
valuesize < (void*).sizeof ? BlkAttr.NO_SCAN : 0);
resi = 0;
foreach (e; aa.b)
{
if (e)
_aaValues_x(e);
}
assert(resi == a.length);
}
return a;
}
/********************************************
* Rehash an array.
*/
void* _aaRehash(AA* paa, TypeInfo keyti)
in
{
//_aaInvAh(paa);
}
out (result)
{
//_aaInvAh(result);
}
body
{
BB newb;
void _aaRehash_x(aaA* olde)
{
while (1)
{
auto left = olde.left;
auto right = olde.right;
olde.left = null;
olde.right = null;
aaA *e;
//printf("rehash %p\n", olde);
auto key_hash = olde.hash;
size_t i = key_hash % newb.b.length;
auto pe = &newb.b[i];
while ((e = *pe) !is null)
{
//printf("\te = %p, e.left = %p, e.right = %p\n", e, e.left, e.right);
assert(e.left != e);
assert(e.right != e);
if (key_hash == e.hash)
{
auto c = keyti.compare(olde + 1, e + 1);
assert(c != 0);
pe = (c < 0) ? &e.left : &e.right;
}
else
pe = (key_hash < e.hash) ? &e.left : &e.right;
}
*pe = olde;
if (right)
{
if (!left)
{ olde = right;
continue;
}
_aaRehash_x(right);
}
if (!left)
break;
olde = left;
}
}
//printf("Rehash\n");
if (*paa)
{
auto aa = *paa;
auto len = _aaLen(aa);
if (len)
{ size_t i;
for (i = 0; i < prime_list.length - 1; i++)
{
if (len <= prime_list[i])
break;
}
len = prime_list[i];
newb.b = new aaA*[len];
newb.keyti = keyti;
foreach (e; aa.b)
{
if (e)
_aaRehash_x(e);
}
newb.nodes = (*aa).nodes;
}
**paa = newb;
}
return *paa;
}
/********************************************
* Produce array of N byte keys from aa.
*/
Array _aaKeys(AA aa, size_t keysize)
{
byte[] res;
size_t resi;
void _aaKeys_x(aaA* e)
{
do
{
memcpy(&res[resi * keysize], cast(byte*)(e + 1), keysize);
resi++;
if (e.left)
{ if (!e.right)
{ e = e.left;
continue;
}
_aaKeys_x(e.left);
}
e = e.right;
} while (e !is null);
}
auto len = _aaLen(aa);
if (!len)
return Array();
res = (cast(byte*) gc_malloc(len * keysize,
!(aa.keyti.flags() & 1) ? BlkAttr.NO_SCAN : 0)) [0 .. len * keysize];
resi = 0;
foreach (e; aa.b)
{
if (e)
_aaKeys_x(e);
}
assert(resi == len);
return Array(len, res.ptr);
}
/**********************************************
* 'apply' for associative arrays - to support foreach
*/
// dg is D, but _aaApply() is C
extern (D) typedef int delegate(void *) dg_t;
int _aaApply(AA aa, size_t keysize, dg_t dg)
in
{
assert(aligntsize(keysize) == keysize);
}
body
{ int result;
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
int treewalker(aaA* e)
{ int result;
do
{
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
result = dg(cast(void *)(e + 1) + keysize);
if (result)
break;
if (e.right)
{ if (!e.left)
{
e = e.right;
continue;
}
result = treewalker(e.right);
if (result)
break;
}
e = e.left;
} while (e);
return result;
}
if (aa)
{
foreach (e; aa.b)
{
if (e)
{
result = treewalker(e);
if (result)
break;
}
}
}
return result;
}
// dg is D, but _aaApply2() is C
extern (D) typedef int delegate(void *, void *) dg2_t;
int _aaApply2(AA aa, size_t keysize, dg2_t dg)
in
{
assert(aligntsize(keysize) == keysize);
}
body
{ int result;
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa, keysize, dg);
int treewalker(aaA* e)
{ int result;
do
{
//printf("treewalker(e = %p, dg = x%llx)\n", e, dg);
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
if (result)
break;
if (e.right)
{ if (!e.left)
{
e = e.right;
continue;
}
result = treewalker(e.right);
if (result)
break;
}
e = e.left;
} while (e);
return result;
}
if (aa)
{
foreach (e; aa.b)
{
if (e)
{
result = treewalker(e);
if (result)
break;
}
}
}
return result;
}
/***********************************
* Construct an associative array of type ti from
* length pairs of key/value pairs.
*/
/+
extern (C)
BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
{
auto valuesize = ti.next.tsize(); // value size
auto keyti = ti.key;
auto keysize = keyti.tsize(); // key size
BB* result;
//printf("_d_assocarrayliteralT(keysize = %d, valuesize = %d, length = %d)\n", keysize, valuesize, length);
//printf("tivalue = %.*s\n", ti.next.classinfo.name);
if (length == 0 || valuesize == 0 || keysize == 0)
{
;
}
else
{
va_list q;
va_start!(size_t)(q, length);
result = new BB();
size_t i;
for (i = 0; i < prime_list.length - 1; i++)
{
if (length <= prime_list[i])
break;
}
auto len = prime_list[i];
result.b = new aaA*[len];
size_t keystacksize = (keysize + int.sizeof - 1) & ~(int.sizeof - 1);
size_t valuestacksize = (valuesize + int.sizeof - 1) & ~(int.sizeof - 1);
size_t keytsize = aligntsize(keysize);
for (size_t j = 0; j < length; j++)
{ void* pkey = q;
q += keystacksize;
void* pvalue = q;
q += valuestacksize;
aaA* e;
auto key_hash = keyti.getHash(pkey);
//printf("hash = %d\n", key_hash);
i = key_hash % len;
auto pe = &result.b[i];
while (1)
{
e = *pe;
if (!e)
{
// Not found, create new elem
//printf("create new one\n");
e = cast(aaA *) cast(void*) new void[aaA.sizeof + keytsize + valuesize];
memcpy(e + 1, pkey, keysize);
e.hash = key_hash;
*pe = e;
result.nodes++;
break;
}
if (key_hash == e.hash)
{
auto c = keyti.compare(pkey, e + 1);
if (c == 0)
break;
pe = (c < 0) ? &e.left : &e.right;
}
else
pe = (key_hash < e.hash) ? &e.left : &e.right;
}
memcpy(cast(void *)(e + 1) + keytsize, pvalue, valuesize);
}
va_end(q);
}
return result;
}
+/

589
runtime/internal/adi.d Normal file
View File

@@ -0,0 +1,589 @@
//_ adi.d
/**
* Part of the D programming language runtime library.
* Dynamic array property support routines
*/
/*
* Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
//debug=adi; // uncomment to turn on debugging printf's
private
{
import tango.stdc.string;
import tango.stdc.stdlib;
import util.utf;
enum BlkAttr : uint
{
FINALIZE = 0b0000_0001,
NO_SCAN = 0b0000_0010,
NO_MOVE = 0b0000_0100,
ALL_BITS = 0b1111_1111
}
extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
extern (C) void* gc_calloc( size_t sz, uint ba = 0 );
extern (C) void gc_free( void* p );
}
struct Array
{
size_t length;
void* ptr;
}
/**********************************************
* Reverse array of chars.
* Handled separately because embedded multibyte encodings should not be
* reversed.
*/
extern (C) Array _adReverseChar(char[] a)
{
if (a.length > 1)
{
char[6] tmp;
char[6] tmplo;
char* lo = a.ptr;
char* hi = &a[length - 1];
while (lo < hi)
{ auto clo = *lo;
auto chi = *hi;
debug(adi) printf("lo = %d, hi = %d\n", lo, hi);
if (clo <= 0x7F && chi <= 0x7F)
{
debug(adi) printf("\tascii\n");
*lo = chi;
*hi = clo;
lo++;
hi--;
continue;
}
uint stridelo = UTF8stride[clo];
uint stridehi = 1;
while ((chi & 0xC0) == 0x80)
{
chi = *--hi;
stridehi++;
assert(hi >= lo);
}
if (lo == hi)
break;
debug(adi) printf("\tstridelo = %d, stridehi = %d\n", stridelo, stridehi);
if (stridelo == stridehi)
{
memcpy(tmp.ptr, lo, stridelo);
memcpy(lo, hi, stridelo);
memcpy(hi, tmp.ptr, stridelo);
lo += stridelo;
hi--;
continue;
}
/* Shift the whole array. This is woefully inefficient
*/
memcpy(tmp.ptr, hi, stridehi);
memcpy(tmplo.ptr, lo, stridelo);
memmove(lo + stridehi, lo + stridelo , cast(size_t)(hi - lo) - stridelo);
memcpy(lo, tmp.ptr, stridehi);
memcpy(hi + stridehi - stridelo, tmplo.ptr, stridelo);
lo += stridehi;
hi = hi - 1 + (stridehi - stridelo);
}
}
return Array(a.length, a.ptr);
}
unittest
{
auto a = "abcd"c;
auto r = a.dup.reverse;
//writefln(r);
assert(r == "dcba");
a = "a\u1235\u1234c";
//writefln(a);
r = a.dup.reverse;
//writefln(r);
assert(r == "c\u1234\u1235a");
a = "ab\u1234c";
//writefln(a);
r = a.dup.reverse;
//writefln(r);
assert(r == "c\u1234ba");
a = "\u3026\u2021\u3061\n";
r = a.dup.reverse;
assert(r == "\n\u3061\u2021\u3026");
}
/**********************************************
* Reverse array of wchars.
* Handled separately because embedded multiword encodings should not be
* reversed.
*/
extern (C) Array _adReverseWchar(wchar[] a)
{
if (a.length > 1)
{
wchar[2] tmp;
wchar* lo = a.ptr;
wchar* hi = &a[length - 1];
while (lo < hi)
{ auto clo = *lo;
auto chi = *hi;
if ((clo < 0xD800 || clo > 0xDFFF) &&
(chi < 0xD800 || chi > 0xDFFF))
{
*lo = chi;
*hi = clo;
lo++;
hi--;
continue;
}
int stridelo = 1 + (clo >= 0xD800 && clo <= 0xDBFF);
int stridehi = 1;
if (chi >= 0xDC00 && chi <= 0xDFFF)
{
chi = *--hi;
stridehi++;
assert(hi >= lo);
}
if (lo == hi)
break;
if (stridelo == stridehi)
{ int stmp;
assert(stridelo == 2);
assert(stmp.sizeof == 2 * (*lo).sizeof);
stmp = *cast(int*)lo;
*cast(int*)lo = *cast(int*)hi;
*cast(int*)hi = stmp;
lo += stridelo;
hi--;
continue;
}
/* Shift the whole array. This is woefully inefficient
*/
memcpy(tmp.ptr, hi, stridehi * wchar.sizeof);
memcpy(hi + stridehi - stridelo, lo, stridelo * wchar.sizeof);
memmove(lo + stridehi, lo + stridelo , (hi - (lo + stridelo)) * wchar.sizeof);
memcpy(lo, tmp.ptr, stridehi * wchar.sizeof);
lo += stridehi;
hi = hi - 1 + (stridehi - stridelo);
}
}
return Array(a.length, a.ptr);
}
unittest
{
wstring a = "abcd";
wstring r;
r = a.dup.reverse;
assert(r == "dcba");
a = "a\U00012356\U00012346c";
r = a.dup.reverse;
assert(r == "c\U00012346\U00012356a");
a = "ab\U00012345c";
r = a.dup.reverse;
assert(r == "c\U00012345ba");
}
/**********************************************
* Support for array.reverse property.
*/
extern (C) Array _adReverse(Array a, size_t szelem)
out (result)
{
assert(result.ptr is a.ptr);
}
body
{
if (a.length >= 2)
{
byte* tmp;
byte[16] buffer;
void* lo = a.ptr;
void* hi = a.ptr + (a.length - 1) * szelem;
tmp = buffer.ptr;
if (szelem > 16)
{
//version (Win32)
//tmp = cast(byte*) alloca(szelem);
//else
tmp = cast(byte*) gc_malloc(szelem);
}
for (; lo < hi; lo += szelem, hi -= szelem)
{
memcpy(tmp, lo, szelem);
memcpy(lo, hi, szelem);
memcpy(hi, tmp, szelem);
}
version (Win32)
{
}
else
{
//if (szelem > 16)
// BUG: bad code is generate for delete pointer, tries
// to call delclass.
//gc_free(tmp);
}
}
return Array(a.length, a.ptr);
}
unittest
{
debug(adi) printf("array.reverse.unittest\n");
int[] a = new int[5];
int[] b;
size_t i;
for (i = 0; i < 5; i++)
a[i] = i;
b = a.reverse;
assert(b is a);
for (i = 0; i < 5; i++)
assert(a[i] == 4 - i);
struct X20
{ // More than 16 bytes in size
int a;
int b, c, d, e;
}
X20[] c = new X20[5];
X20[] d;
for (i = 0; i < 5; i++)
{ c[i].a = i;
c[i].e = 10;
}
d = c.reverse;
assert(d is c);
for (i = 0; i < 5; i++)
{
assert(c[i].a == 4 - i);
assert(c[i].e == 10);
}
}
/**********************************************
* Sort array of chars.
*/
extern (C) Array _adSortChar(char[] a)
{
if (a.length > 1)
{
dchar[] da = toUTF32(a);
da.sort;
size_t i = 0;
foreach (dchar d; da)
{ char[4] buf;
auto t = toUTF8(buf, d);
a[i .. i + t.length] = t[];
i += t.length;
}
delete da;
}
return Array(a.length, a.ptr);
}
/**********************************************
* Sort array of wchars.
*/
extern (C) Array _adSortWchar(wchar[] a)
{
if (a.length > 1)
{
dchar[] da = toUTF32(a);
da.sort;
size_t i = 0;
foreach (dchar d; da)
{ wchar[2] buf;
auto t = toUTF16(buf, d);
a[i .. i + t.length] = t[];
i += t.length;
}
delete da;
}
return Array(a.length, a.ptr);
}
/***************************************
* Support for array equality test.
*/
extern (C) int _adEq(Array a1, Array a2, TypeInfo ti)
{
debug(adi) printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length);
if (a1.length != a2.length)
return 0; // not equal
else if (a1.ptr == a2.ptr)
return 1; // equal
// let typeinfo decide
return ti.equals(&a1, &a2);
}
unittest
{
debug(adi) printf("array.Eq unittest\n");
auto a = "hello"c;
assert(a != "hel");
assert(a != "helloo");
assert(a != "betty");
assert(a == "hello");
assert(a != "hxxxx");
}
/***************************************
* Support for array compare test.
*/
extern (C) int _adCmp(Array a1, Array a2, TypeInfo ti)
{
debug(adi) printf("adCmp()\n");
if (a1.ptr == a2.ptr &&
a1.length == a2.length)
return 0;
auto len = a1.length;
if (a2.length < len)
len = a2.length;
// let typeinfo decide
return ti.compare(&a1, &a2);
}
unittest
{
debug(adi) printf("array.Cmp unittest\n");
auto a = "hello"c;
assert(a > "hel");
assert(a >= "hel");
assert(a < "helloo");
assert(a <= "helloo");
assert(a > "betty");
assert(a >= "betty");
assert(a == "hello");
assert(a <= "hello");
assert(a >= "hello");
}
/***************************************
* Support for array compare test.
*/
extern (C) int _adCmpChar(Array a1, Array a2)
{
version(D_InlineAsm_X86)
{
//version = Asm86;
}
version (Asm86)
{
asm
{ naked ;
push EDI ;
push ESI ;
mov ESI,a1+4[4+ESP] ;
mov EDI,a2+4[4+ESP] ;
mov ECX,a1[4+ESP] ;
mov EDX,a2[4+ESP] ;
cmp ECX,EDX ;
jb GotLength ;
mov ECX,EDX ;
GotLength:
cmp ECX,4 ;
jb DoBytes ;
// Do alignment if neither is dword aligned
test ESI,3 ;
jz Aligned ;
test EDI,3 ;
jz Aligned ;
DoAlign:
mov AL,[ESI] ; //align ESI to dword bounds
mov DL,[EDI] ;
cmp AL,DL ;
jnz Unequal ;
inc ESI ;
inc EDI ;
test ESI,3 ;
lea ECX,[ECX-1] ;
jnz DoAlign ;
Aligned:
mov EAX,ECX ;
// do multiple of 4 bytes at a time
shr ECX,2 ;
jz TryOdd ;
repe ;
cmpsd ;
jnz UnequalQuad ;
TryOdd:
mov ECX,EAX ;
DoBytes:
// if still equal and not end of string, do up to 3 bytes slightly
// slower.
and ECX,3 ;
jz Equal ;
repe ;
cmpsb ;
jnz Unequal ;
Equal:
mov EAX,a1[4+ESP] ;
mov EDX,a2[4+ESP] ;
sub EAX,EDX ;
pop ESI ;
pop EDI ;
ret ;
UnequalQuad:
mov EDX,[EDI-4] ;
mov EAX,[ESI-4] ;
cmp AL,DL ;
jnz Unequal ;
cmp AH,DH ;
jnz Unequal ;
shr EAX,16 ;
shr EDX,16 ;
cmp AL,DL ;
jnz Unequal ;
cmp AH,DH ;
Unequal:
sbb EAX,EAX ;
pop ESI ;
or EAX,1 ;
pop EDI ;
ret ;
}
}
else
{
int len;
int c;
debug(adi) printf("adCmpChar()\n");
len = cast(int)a1.length;
if (a2.length < len)
len = cast(int)a2.length;
c = memcmp(cast(char *)a1.ptr, cast(char *)a2.ptr, len);
if (!c)
c = cast(int)a1.length - cast(int)a2.length;
return c;
}
}
unittest
{
debug(adi) printf("array.CmpChar unittest\n");
auto a = "hello"c;
assert(a > "hel");
assert(a >= "hel");
assert(a < "helloo");
assert(a <= "helloo");
assert(a > "betty");
assert(a >= "betty");
assert(a == "hello");
assert(a <= "hello");
assert(a >= "hello");
}

View File

@@ -0,0 +1,107 @@
private import llvmdc.intrinsics;
extern(C):
int memcmp(void*,void*,size_t);
size_t strlen(char*);
version(LLVM64)
alias llvm_memcpy_i64 llvm_memcpy;
else
alias llvm_memcpy_i32 llvm_memcpy;
// per-element array init routines
void _d_array_init_i1(bool* a, size_t n, bool v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_i8(ubyte* a, size_t n, ubyte v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_i16(ushort* a, size_t n, ushort v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_i32(uint* a, size_t n, uint v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_i64(ulong* a, size_t n, ulong v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_float(float* a, size_t n, float v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_double(double* a, size_t n, double v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_real(real* a, size_t n, real v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_pointer(void** a, size_t n, void* v)
{
auto p = a;
auto end = a+n;
while (p !is end)
*p++ = v;
}
void _d_array_init_mem(void* a, size_t na, void* v, size_t nv)
{
auto p = a;
auto end = a + na*nv;
while (p !is end) {
llvm_memcpy(p,v,nv,0);
p += nv;
}
}
// for array cast
size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
{
if (newelemsz == 1) {
return len*elemsz;
}
else if (len % newelemsz) {
throw new Exception("Bad array cast");
}
return (len*elemsz)/newelemsz;
}

196
runtime/internal/cast.d Normal file
View 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);
}

160
runtime/internal/critical.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* Placed into the Public Domain
* written by Walter Bright, Digital Mars
* www.digitalmars.com
*/
/* ================================= Win32 ============================ */
#if _WIN32
#include <windows.h>
/******************************************
* Enter/exit critical section.
*/
/* We don't initialize critical sections unless we actually need them.
* So keep a linked list of the ones we do use, and in the static destructor
* code, walk the list and release them.
*/
typedef struct D_CRITICAL_SECTION
{
struct D_CRITICAL_SECTION *next;
CRITICAL_SECTION cs;
} D_CRITICAL_SECTION;
static D_CRITICAL_SECTION *dcs_list;
static D_CRITICAL_SECTION critical_section;
static volatile int inited;
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
{
if (!dcs->next)
{
EnterCriticalSection(&critical_section.cs);
if (!dcs->next) // if, in the meantime, another thread didn't set it
{
dcs->next = dcs_list;
dcs_list = dcs;
InitializeCriticalSection(&dcs->cs);
}
LeaveCriticalSection(&critical_section.cs);
}
EnterCriticalSection(&dcs->cs);
}
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
{
LeaveCriticalSection(&dcs->cs);
}
void _STI_critical_init()
{
if (!inited)
{ InitializeCriticalSection(&critical_section.cs);
dcs_list = &critical_section;
inited = 1;
}
}
void _STD_critical_term()
{
if (inited)
{ inited = 0;
while (dcs_list)
{
DeleteCriticalSection(&dcs_list->cs);
dcs_list = dcs_list->next;
}
}
}
#endif
/* ================================= linux ============================ */
#if linux
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
/******************************************
* Enter/exit critical section.
*/
/* We don't initialize critical sections unless we actually need them.
* So keep a linked list of the ones we do use, and in the static destructor
* code, walk the list and release them.
*/
typedef struct D_CRITICAL_SECTION
{
struct D_CRITICAL_SECTION *next;
pthread_mutex_t cs;
} D_CRITICAL_SECTION;
static D_CRITICAL_SECTION *dcs_list;
static D_CRITICAL_SECTION critical_section;
static pthread_mutexattr_t _criticals_attr;
void _STI_critical_init(void);
void _STD_critical_term(void);
void _d_criticalenter(D_CRITICAL_SECTION *dcs)
{
if (!dcs_list)
{ _STI_critical_init();
atexit(_STD_critical_term);
}
//printf("_d_criticalenter(dcs = x%x)\n", dcs);
if (!dcs->next)
{
pthread_mutex_lock(&critical_section.cs);
if (!dcs->next) // if, in the meantime, another thread didn't set it
{
dcs->next = dcs_list;
dcs_list = dcs;
pthread_mutex_init(&dcs->cs, &_criticals_attr);
}
pthread_mutex_unlock(&critical_section.cs);
}
pthread_mutex_lock(&dcs->cs);
}
void _d_criticalexit(D_CRITICAL_SECTION *dcs)
{
//printf("_d_criticalexit(dcs = x%x)\n", dcs);
pthread_mutex_unlock(&dcs->cs);
}
void _STI_critical_init()
{
if (!dcs_list)
{ //printf("_STI_critical_init()\n");
pthread_mutexattr_init(&_criticals_attr);
pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP);
// The global critical section doesn't need to be recursive
pthread_mutex_init(&critical_section.cs, 0);
dcs_list = &critical_section;
}
}
void _STD_critical_term()
{
if (dcs_list)
{ //printf("_STI_critical_term()\n");
while (dcs_list)
{
//printf("\tlooping... %x\n", dcs_list);
pthread_mutex_destroy(&dcs_list->cs);
dcs_list = dcs_list->next;
}
}
}
#endif

293
runtime/internal/dmain2.d Normal file
View File

@@ -0,0 +1,293 @@
/*
* Placed into the Public Domain.
* written by Walter Bright
* www.digitalmars.com
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
private
{
import util.console;
import tango.stdc.stddef;
import tango.stdc.stdlib;
import tango.stdc.string;
}
version( Win32 )
{
extern (Windows) void* LocalFree(void*);
extern (Windows) wchar_t* GetCommandLineW();
extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*);
extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
//pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW
//pragma(lib, "tango-win32-dmd.lib"); // links Tango's Win32 library to reduce EXE size
}
extern (C) void _STI_monitor_staticctor();
extern (C) void _STD_monitor_staticdtor();
extern (C) void _STI_critical_init();
extern (C) void _STD_critical_term();
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _moduleCtor();
extern (C) void _moduleDtor();
extern (C) void thread_joinAll();
//debug=PRINTF;
debug(PRINTF) extern (C) int printf(char*, ...);
/***********************************
* These functions must be defined for any D program linked
* against this library.
*/
extern (C) void onAssertError( char[] file, size_t line );
extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg );
extern (C) void onArrayBoundsError( char[] file, size_t line );
extern (C) void onSwitchError( char[] file, size_t line );
extern (C) bool runModuleUnitTests();
// this function is called from the utf module
//extern (C) void onUnicodeError( char[] msg, size_t idx );
/***********************************
* These are internal callbacks for various language errors.
*/
extern (C) void _d_assert( char[] file, uint line )
{
onAssertError( file, line );
}
extern (C) void _d_assert_msg( char[] msg, char[] file, uint line )
{
onAssertErrorMsg( file, line, msg );
}
extern (C) void _d_array_bounds( char[] file, uint line )
{
onArrayBoundsError( file, line );
}
extern (C) void _d_switch_error( char[] file, uint line )
{
onSwitchError( file, line );
}
bool _d_isHalting = false;
extern (C) bool rt_isHalting()
{
return _d_isHalting;
}
extern (C) bool rt_trapExceptions = true;
void _d_criticalInit()
{
_STI_monitor_staticctor();
_STI_critical_init();
}
alias void delegate( Exception ) ExceptionHandler;
// this is here so users can manually initialize the runtime
// for example, when there is no main function etc.
extern (C) bool rt_init( ExceptionHandler dg = null )
{
_d_criticalInit();
try
{
gc_init();
_moduleCtor();
return true;
}
catch( Exception e )
{
if( dg )
dg( e );
}
catch
{
}
_d_criticalTerm();
return false;
}
void _d_criticalTerm()
{
_STD_critical_term();
_STD_monitor_staticdtor();
}
// this is here so users can manually terminate the runtime
// for example, when there is no main function etc.
extern (C) bool rt_term( ExceptionHandler dg = null )
{
try
{
thread_joinAll();
_d_isHalting = true;
_moduleDtor();
gc_term();
return true;
}
catch( Exception e )
{
if( dg )
dg( e );
}
catch
{
}
finally
{
_d_criticalTerm();
}
return false;
}
/***********************************
* The D main() function supplied by the user's program
*/
int main(char[][] args);
/***********************************
* Substitutes for the C main() function.
* It's purpose is to wrap the call to the D main()
* function and catch any unhandled exceptions.
*/
extern (C) int main(int argc, char **argv, char** env)
{
char[][] args;
int result;
debug(PRINTF) printf("main ctors\n");
_STI_monitor_staticctor();
_STI_critical_init();
debug(PRINTF) printf("main args\n");
version (Win32)
{
wchar_t* wcbuf = GetCommandLineW();
size_t wclen = wcslen(wcbuf);
int wargc = 0;
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
assert(wargc == argc);
char* cargp = null;
size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
cargp = cast(char*) alloca(cargl);
args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
for (size_t i = 0, p = 0; i < wargc; i++)
{
int wlen = wcslen( wargs[i] );
int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
args[i] = cargp[p .. p+clen];
p += clen; assert(p <= cargl);
WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
}
LocalFree(wargs);
wargs = null;
wargc = 0;
}
else version (linux)
{
char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
scope(exit) free(am);
for (size_t i = 0; i < argc; i++)
{
auto len = strlen(argv[i]);
am[i] = argv[i][0 .. len];
}
args = am[0 .. argc];
}
debug(PRINTF) printf("main trap exceptions\n");
bool trapExceptions = rt_trapExceptions;
void tryExec(void delegate() dg)
{
debug(PRINTF) printf("main try exec\n");
if (trapExceptions)
{
try
{
dg();
}
catch (Exception e)
{
while (e)
{
if (e.file)
{
debug(PRINTF) printf("%.*s(%u): %.*s\n", e.file.length, e.file.ptr, e.line, e.msg.length, e.msg.ptr);
console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
}
else
{
// debug(PRINTF) printf("%.*s\n", e.toString());
console (e.classinfo.name)(": ")(e.toString)("\n");
}
e = e.next;
}
result = EXIT_FAILURE;
}
catch (Object o)
{
// fprintf(stderr, "%.*s\n", o.toString());
console (o.toString)("\n");
result = EXIT_FAILURE;
}
}
else
{
dg();
}
}
// NOTE: The lifetime of a process is much like the lifetime of an object:
// it is initialized, then used, then destroyed. If initialization
// fails, the successive two steps are never reached. However, if
// initialization succeeds, then cleanup will occur even if the use
// step fails in some way. Here, the use phase consists of running
// the user's main function. If main terminates with an exception,
// the exception is handled and then cleanup begins. An exception
// thrown during cleanup, however, will abort the cleanup process.
void runMain()
{
debug(PRINTF) printf("main runMain\n");
result = main(args);
}
void runAll()
{
debug(PRINTF) printf("main runAll\n");
gc_init();
_moduleCtor();
if (runModuleUnitTests())
tryExec(&runMain);
thread_joinAll();
_d_isHalting = true;
_moduleDtor();
gc_term();
}
tryExec(&runAll);
debug(PRINTF) printf("main dtor\n");
_STD_critical_term();
_STD_monitor_staticdtor();
return result;
}

356
runtime/internal/eh.d Normal file
View File

@@ -0,0 +1,356 @@
/**
* This module contains functions and structures required for
* exception handling.
*/
module eh;
import util.console;
// debug = EH_personality;
// current EH implementation works on x86 linux only
version(X86) version(linux) version=X86_LINUX;
private extern(C) void abort();
private extern(C) int printf(char*, ...);
// D runtime functions
extern(C) {
int _d_isbaseof(ClassInfo oc, ClassInfo c);
}
// libunwind headers
extern(C)
{
enum _Unwind_Reason_Code
{
NO_REASON = 0,
FOREIGN_EXCEPTION_CAUGHT = 1,
FATAL_PHASE2_ERROR = 2,
FATAL_PHASE1_ERROR = 3,
NORMAL_STOP = 4,
END_OF_STACK = 5,
HANDLER_FOUND = 6,
INSTALL_CONTEXT = 7,
CONTINUE_UNWIND = 8
}
enum _Unwind_Action
{
SEARCH_PHASE = 1,
CLEANUP_PHASE = 2,
HANDLER_PHASE = 3,
FORCE_UNWIND = 4
}
alias void* _Unwind_Context_Ptr;
alias void function(_Unwind_Reason_Code, _Unwind_Exception*) _Unwind_Exception_Cleanup_Fn;
struct _Unwind_Exception
{
char[8] exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
int private_1;
int private_2;
}
version(X86_LINUX)
{
void _Unwind_Resume(_Unwind_Exception*);
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*);
ulong _Unwind_GetLanguageSpecificData(_Unwind_Context_Ptr context);
ulong _Unwind_GetIP(_Unwind_Context_Ptr context);
ulong _Unwind_SetIP(_Unwind_Context_Ptr context, ulong new_value);
ulong _Unwind_SetGR(_Unwind_Context_Ptr context, int index, ulong new_value);
ulong _Unwind_GetRegionStart(_Unwind_Context_Ptr context);
}
else
{
// runtime calls these directly
void _Unwind_Resume(_Unwind_Exception*)
{
console("_Unwind_Resume is not implemented on this platform.\n");
}
_Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception*)
{
console("_Unwind_RaiseException is not implemented on this platform.\n");
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
}
}
}
// helpers for reading certain DWARF data
//TODO: It may not be a good idea to use exceptions for error handling within exception handling code
private ubyte* get_uleb128(ubyte* addr, ref size_t res)
{
res = 0;
size_t bitsize = 0;
// read as long as high bit is set
while(*addr & 0x80) {
res |= (*addr & 0x7f) << bitsize;
bitsize += 7;
addr += 1;
if(bitsize >= size_t.sizeof*8)
throw new Exception("tried to read uleb128 that exceeded size of size_t");
}
// read last
if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
throw new Exception("tried to read uleb128 that exceeded size of size_t");
res |= (*addr) << bitsize;
return addr + 1;
}
private ubyte* get_sleb128(ubyte* addr, ref ptrdiff_t res)
{
res = 0;
size_t bitsize = 0;
// read as long as high bit is set
while(*addr & 0x80) {
res |= (*addr & 0x7f) << bitsize;
bitsize += 7;
addr += 1;
if(bitsize >= size_t.sizeof*8)
throw new Exception("tried to read sleb128 that exceeded size of size_t");
}
// read last
if(bitsize != 0 && *addr >= 1 << size_t.sizeof*8 - bitsize)
throw new Exception("tried to read sleb128 that exceeded size of size_t");
res |= (*addr) << bitsize;
// take care of sign
if(bitsize < size_t.sizeof*8 && ((*addr) & 0x40))
res |= cast(ptrdiff_t)(-1) ^ ((1 << (bitsize+7)) - 1);
return addr + 1;
}
// exception struct used by the runtime.
// _d_throw allocates a new instance and passes the address of its
// _Unwind_Exception member to the unwind call. The personality
// routine is then able to get the whole struct by looking at the data
// surrounding the unwind info.
struct _d_exception
{
Object exception_object;
_Unwind_Exception unwind_info;
}
// the 8-byte string identifying the type of exception
// the first 4 are for vendor, the second 4 for language
//TODO: This may be the wrong way around
char[8] _d_exception_class = "LLDCD1\0\0";
//
// x86 Linux specific implementation of personality function
// and helpers
//
version(X86_LINUX)
{
// the personality routine gets called by the unwind handler and is responsible for
// reading the EH tables and deciding what to do
extern(C) _Unwind_Reason_Code _d_eh_personality(int ver, _Unwind_Action actions, ulong exception_class, _Unwind_Exception* exception_info, _Unwind_Context_Ptr context)
{
// check ver: the C++ Itanium ABI only allows ver == 1
if(ver != 1)
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
// check exceptionClass
//TODO: Treat foreign exceptions with more respect
if((cast(char*)&exception_class)[0..8] != _d_exception_class)
return _Unwind_Reason_Code.FATAL_PHASE1_ERROR;
// find call site table, action table and classinfo table
// Note: callsite and action tables do not contain static-length
// data and will be parsed as needed
// Note: classinfo_table points past the end of the table
ubyte* callsite_table;
ubyte* action_table;
ClassInfo* classinfo_table;
_d_getLanguageSpecificTables(context, callsite_table, action_table, classinfo_table);
/*
find landing pad and action table index belonging to ip by walking
the callsite_table
*/
ubyte* callsite_walker = callsite_table;
// get the instruction pointer
// will be used to find the right entry in the callsite_table
// -1 because it will point past the last instruction
ulong ip = _Unwind_GetIP(context) - 1;
// address block_start is relative to
ulong region_start = _Unwind_GetRegionStart(context);
// table entries
uint block_start_offset, block_size;
ulong landing_pad;
size_t action_offset;
while(true) {
// if we've gone through the list and found nothing...
if(callsite_walker >= action_table)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
block_start_offset = *cast(uint*)callsite_walker;
block_size = *(cast(uint*)callsite_walker + 1);
landing_pad = *(cast(uint*)callsite_walker + 2);
if(landing_pad)
landing_pad += region_start;
callsite_walker = get_uleb128(callsite_walker + 3*uint.sizeof, action_offset);
debug(EH_personality_verbose) printf("%d %d %d\n", block_start_offset, block_size, landing_pad);
// since the list is sorted, as soon as we're past the ip
// there's no handler to be found
if(ip < region_start + block_start_offset)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
// if we've found our block, exit
if(ip < region_start + block_start_offset + block_size)
break;
}
debug(EH_personality) printf("Found correct landing pad and actionOffset %d\n", action_offset);
// now we need the exception's classinfo to find a handler
// the exception_info is actually a member of a larger _d_exception struct
// the runtime allocated. get that now
_d_exception* exception_struct = cast(_d_exception*)(cast(ubyte*)exception_info - _d_exception.unwind_info.offsetof);
// if there's no action offset and no landing pad, continue unwinding
if(!action_offset && !landing_pad)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
// if there's no action offset but a landing pad, this is a cleanup handler
else if(!action_offset && landing_pad)
return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
/*
walk action table chain, comparing classinfos using _d_isbaseof
*/
ubyte* action_walker = action_table + action_offset - 1;
ptrdiff_t ti_offset, next_action_offset;
while(true) {
action_walker = get_sleb128(action_walker, ti_offset);
// it is intentional that we not modify action_walker here
// next_action_offset is from current action_walker position
get_sleb128(action_walker, next_action_offset);
// negative are 'filters' which we don't use
assert(ti_offset >= 0 && "Filter actions are unsupported");
// zero means cleanup, which we require to be the last action
if(ti_offset == 0) {
assert(next_action_offset == 0 && "Cleanup action must be last in chain");
return _d_eh_install_finally_context(actions, landing_pad, exception_struct, context);
}
// get classinfo for action and check if the one in the
// exception structure is a base
ClassInfo catch_ci = classinfo_table[-ti_offset];
debug(EH_personality) printf("Comparing catch %s to exception %s\n", catch_ci.name.ptr, exception_struct.exception_object.classinfo.name.ptr);
if(_d_isbaseof(exception_struct.exception_object.classinfo, catch_ci))
return _d_eh_install_catch_context(actions, ti_offset, landing_pad, exception_struct, context);
// we've walked through all actions and found nothing...
if(next_action_offset == 0)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
else
action_walker += next_action_offset;
}
assert(false);
}
// These are the register numbers for SetGR that
// llvm's eh.exception and eh.selector intrinsics
// will pick up.
// Found by trial-and-error and probably platform dependent!
private int eh_exception_regno = 0;
private int eh_selector_regno = 2;
private _Unwind_Reason_Code _d_eh_install_catch_context(_Unwind_Action actions, ptrdiff_t switchval, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
{
debug(EH_personality) printf("Found catch clause!\n");
if(actions & _Unwind_Action.SEARCH_PHASE)
return _Unwind_Reason_Code.HANDLER_FOUND;
else if(actions & _Unwind_Action.HANDLER_PHASE)
{
debug(EH_personality) printf("Setting switch value to: %d!\n", switchval);
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)cast(void*)(exception_struct.exception_object));
_Unwind_SetGR(context, eh_selector_regno, switchval);
_Unwind_SetIP(context, landing_pad);
return _Unwind_Reason_Code.INSTALL_CONTEXT;
}
assert(false);
}
private _Unwind_Reason_Code _d_eh_install_finally_context(_Unwind_Action actions, ulong landing_pad, _d_exception* exception_struct, _Unwind_Context_Ptr context)
{
// if we're merely in search phase, continue
if(actions & _Unwind_Action.SEARCH_PHASE)
return _Unwind_Reason_Code.CONTINUE_UNWIND;
debug(EH_personality) printf("Calling cleanup routine...\n");
_Unwind_SetGR(context, eh_exception_regno, cast(ulong)exception_struct);
_Unwind_SetGR(context, eh_selector_regno, 0);
_Unwind_SetIP(context, landing_pad);
return _Unwind_Reason_Code.INSTALL_CONTEXT;
}
private void _d_getLanguageSpecificTables(_Unwind_Context_Ptr context, ref ubyte* callsite, ref ubyte* action, ref ClassInfo* ci)
{
ubyte* data = cast(ubyte*)_Unwind_GetLanguageSpecificData(context);
//TODO: Do proper DWARF reading here
assert(*data++ == 0xff);
assert(*data++ == 0x00);
size_t cioffset;
data = get_uleb128(data, cioffset);
ci = cast(ClassInfo*)(data + cioffset);
assert(*data++ == 0x03);
size_t callsitelength;
data = get_uleb128(data, callsitelength);
action = data + callsitelength;
callsite = data;
}
} // end of x86 Linux specific implementation
extern(C) void _d_throw_exception(Object e)
{
if (e !is null)
{
_d_exception* exc_struct = new _d_exception;
exc_struct.unwind_info.exception_class[] = _d_exception_class;
exc_struct.exception_object = e;
_Unwind_Reason_Code ret = _Unwind_RaiseException(&exc_struct.unwind_info);
console("_Unwind_RaiseException failed with reason code: ")(ret)("\n");
}
abort();
}
extern(C) void _d_eh_resume_unwind(_d_exception* exception_struct)
{
_Unwind_Resume(&exception_struct.unwind_info);
}

1294
runtime/internal/genobj.d Normal file

File diff suppressed because it is too large Load Diff

1052
runtime/internal/lifetime.d Normal file

File diff suppressed because it is too large Load Diff

174
runtime/internal/llvmdc.mak Normal file
View File

@@ -0,0 +1,174 @@
# Makefile to build the LLVMDC compiler runtime D library for Linux
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the compiler runtime library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-base-llvmdc.a
LIB_MASK=libtango-base-llvmdc*.a
LIB_TARGET_C=libtango-base-c-llvmdc.a
LIB_MASK_C=libtango-base-c-llvmdc*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
#CFLAGS=-O3 $(ADD_CFLAGS)
CFLAGS=-g $(ADD_CFLAGS)
#DFLAGS=-release -O3 -inline -w $(ADD_DFLAGS)
DFLAGS=-g -w $(ADD_DFLAGS)
#TFLAGS=-O3 -inline -w $(ADD_DFLAGS)
TFLAGS=-g -w $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=gcc
LC=llvm-ar rsv
CLC=ar rsv
DC=llvmdc
LLC=llvm-as
LIB_DEST=..
.SUFFIXES: .s .S .c .cpp .d .ll .html .o .bc
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.bc:
$(DC) -c $(DFLAGS) $< -of$@
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html llvmdc.ddoc $<
targets : lib doc
all : lib doc
lib : llvmdc.lib llvmdc.clib
doc : llvmdc.doc
######################################################
OBJ_C= \
monitor.o \
critical.o
OBJ_BASE= \
aaA.bc \
aApply.bc \
aApplyR.bc \
adi.bc \
arrayInit.bc \
cast.bc \
dmain2.bc \
eh.bc \
genobj.bc \
lifetime.bc \
memory.bc \
qsort2.bc \
switch.bc \
OBJ_UTIL= \
util/console.bc \
util/ctype.bc \
util/string.bc \
util/utf.bc
OBJ_LLVMDC= \
llvmdc/bitmanip.bc \
llvmdc/vararg.bc
OBJ_TI= \
typeinfo/ti_AC.bc \
typeinfo/ti_Acdouble.bc \
typeinfo/ti_Acfloat.bc \
typeinfo/ti_Acreal.bc \
typeinfo/ti_Adouble.bc \
typeinfo/ti_Afloat.bc \
typeinfo/ti_Ag.bc \
typeinfo/ti_Aint.bc \
typeinfo/ti_Along.bc \
typeinfo/ti_Areal.bc \
typeinfo/ti_Ashort.bc \
typeinfo/ti_byte.bc \
typeinfo/ti_C.bc \
typeinfo/ti_cdouble.bc \
typeinfo/ti_cfloat.bc \
typeinfo/ti_char.bc \
typeinfo/ti_creal.bc \
typeinfo/ti_dchar.bc \
typeinfo/ti_delegate.bc \
typeinfo/ti_double.bc \
typeinfo/ti_float.bc \
typeinfo/ti_idouble.bc \
typeinfo/ti_ifloat.bc \
typeinfo/ti_int.bc \
typeinfo/ti_ireal.bc \
typeinfo/ti_long.bc \
typeinfo/ti_ptr.bc \
typeinfo/ti_real.bc \
typeinfo/ti_short.bc \
typeinfo/ti_ubyte.bc \
typeinfo/ti_uint.bc \
typeinfo/ti_ulong.bc \
typeinfo/ti_ushort.bc \
typeinfo/ti_void.bc \
typeinfo/ti_wchar.bc
ALL_OBJS= \
$(OBJ_BASE) \
$(OBJ_UTIL) \
$(OBJ_TI) \
$(OBJ_LLVMDC)
######################################################
ALL_DOCS=
######################################################
llvmdc.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
llvmdc.clib : $(LIB_TARGET_C)
$(LIB_TARGET_C) : $(OBJ_C)
$(RM) $@
$(CLC) $@ $(OBJ_C)
llvmdc.doc : $(ALL_DOCS)
echo No documentation available.
######################################################
clean :
find . -name "*.di" | xargs $(RM)
$(RM) $(ALL_OBJS)
$(RM) $(OBJ_C)
$(RM) $(ALL_DOCS)
$(RM) $(LIB_MASK)
$(RM) $(LIB_MASK_C)
install :
$(MD) $(LIB_DEST)
$(CP) $(LIB_MASK) $(LIB_DEST)/.
$(CP) $(LIB_MASK_C) $(LIB_DEST)/.

View File

@@ -0,0 +1,81 @@
/*
* D phobos intrinsics for LLVMDC
*
* From GDC ... public domain!
*/
module llvmdc.bitmanip;
// Check for the right compiler
version(LLVMDC)
{
// OK
}
else
{
static assert(false, "This module is only valid for LLVMDC");
}
int bsf(uint v)
{
uint m = 1;
uint i;
for (i = 0; i < 32; i++,m<<=1) {
if (v&m)
return i;
}
return i; // supposed to be undefined
}
int bsr(uint v)
{
uint m = 0x80000000;
uint i;
for (i = 32; i ; i--,m>>>=1) {
if (v&m)
return i-1;
}
return i; // supposed to be undefined
}
int bt(uint *p, uint bitnum)
{
return (p[bitnum / (uint.sizeof*8)] & (1<<(bitnum & ((uint.sizeof*8)-1)))) ? -1 : 0 ;
}
int btc(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q ^= mask;
return result ? -1 : 0;
}
int btr(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q &= ~mask;
return result ? -1 : 0;
}
int bts(uint *p, uint bitnum)
{
uint * q = p + (bitnum / (uint.sizeof*8));
uint mask = 1 << (bitnum & ((uint.sizeof*8) - 1));
int result = *q & mask;
*q |= mask;
return result ? -1 : 0;
}
pragma(intrinsic, "llvm.bswap.i32")
uint bswap(uint val);
ubyte inp(uint p) { return 0; }
ushort inpw(uint p) { return 0; }
uint inpl(uint p) { return 0; }
ubyte outp(uint p, ubyte v) { return v; }
ushort outpw(uint p, ushort v) { return v; }
uint outpl(uint p, uint v) { return v; }

View File

@@ -0,0 +1,43 @@
/*
* This module holds the implementation of special vararg templates for D style var args.
*
* Provides the functions tango.core.Vararg expects to be present!
*/
module llvmdc.Vararg;
// Check for the right compiler
version(LLVMDC)
{
// OK
}
else
{
static assert(false, "This module is only valid for LLVMDC");
}
alias void* va_list;
void va_start(T) ( out va_list ap, inout T parmn )
{
// not needed !
}
T va_arg(T)(ref va_list vp)
{
T* arg = cast(T*) vp;
// llvmdc always aligns to size_t.sizeof in vararg lists
vp = cast(va_list) ( cast(void*) vp + ( ( T.sizeof + size_t.sizeof - 1 ) & ~( size_t.sizeof - 1 ) ) );
return *arg;
}
void va_end( va_list ap )
{
// not needed !
}
void va_copy( out va_list dst, va_list src )
{
// seems pretty useless !
dst = src;
}

105
runtime/internal/mars.h Normal file
View File

@@ -0,0 +1,105 @@
/*
* Placed into the Public Domain
* written by Walter Bright, Digital Mars
* www.digitalmars.com
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
#include <stddef.h>
#if __cplusplus
extern "C" {
#endif
struct ClassInfo;
struct Vtbl;
typedef struct Vtbl
{
size_t len;
void **vptr;
} Vtbl;
typedef struct Interface
{
struct ClassInfo *classinfo;
struct Vtbl vtbl;
int offset;
} Interface;
typedef struct Object
{
void **vptr;
void *monitor;
} Object;
typedef struct ClassInfo
{
Object object;
size_t initlen;
void *init;
size_t namelen;
char *name;
Vtbl vtbl;
size_t interfacelen;
Interface *interfaces;
struct ClassInfo *baseClass;
void *destructor;
void *invariant;
int flags;
} ClassInfo;
typedef struct Exception
{
Object object;
size_t msglen;
char* msg;
size_t filelen;
char* file;
size_t line;
struct Interface *info;
struct Exception *next;
} Exception;
typedef struct Array
{
size_t length;
void *ptr;
} Array;
typedef struct Delegate
{
void *thisptr;
void (*funcptr)();
} Delegate;
void _d_monitorenter(Object *h);
void _d_monitorexit(Object *h);
int _d_isbaseof(ClassInfo *b, ClassInfo *c);
Object *_d_dynamic_cast(Object *o, ClassInfo *ci);
Object * _d_newclass(ClassInfo *ci);
void _d_delclass(Object **p);
void _d_OutOfMemory();
#if __cplusplus
}
#endif

173
runtime/internal/memory.d Normal file
View File

@@ -0,0 +1,173 @@
/**
* This module exposes functionality for inspecting and manipulating memory.
*
* Copyright: Copyright (C) 2005-2006 Digital Mars, www.digitalmars.com.
* All rights reserved.
* License:
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
* Authors: Walter Bright, Sean Kelly
*/
module memory;
private
{
version( linux )
{
//version = SimpleLibcStackEnd;
version( SimpleLibcStackEnd )
{
extern (C) extern void* __libc_stack_end;
}
else
{
import tango.stdc.posix.dlfcn;
}
}
version(LLVMDC)
{
pragma(intrinsic, "llvm.frameaddress")
{
void* llvm_frameaddress(uint level=0);
}
}
}
/**
*
*/
extern (C) void* rt_stackBottom()
{
version( Win32 )
{
asm
{
naked;
mov EAX,FS:4;
ret;
}
}
else version( linux )
{
version( SimpleLibcStackEnd )
{
return __libc_stack_end;
}
else
{
// See discussion: http://autopackage.org/forums/viewtopic.php?t=22
static void** libc_stack_end;
if( libc_stack_end == libc_stack_end.init )
{
void* handle = dlopen( null, RTLD_NOW );
libc_stack_end = cast(void**) dlsym( handle, "__libc_stack_end" );
dlclose( handle );
}
return *libc_stack_end;
}
}
else
{
static assert( false, "Operating system not supported." );
}
}
/**
*
*/
extern (C) void* rt_stackTop()
{
version(LLVMDC)
{
return llvm_frameaddress();
}
else version( D_InlineAsm_X86 )
{
asm
{
naked;
mov EAX, ESP;
ret;
}
}
else
{
static assert( false, "Architecture not supported." );
}
}
private
{
version( Win32 )
{
extern (C)
{
extern int _data_start__;
extern int _bss_end__;
alias _data_start__ Data_Start;
alias _bss_end__ Data_End;
}
}
else version( linux )
{
extern (C)
{
extern int _data;
extern int __data_start;
extern int _end;
extern int _data_start__;
extern int _data_end__;
extern int _bss_start__;
extern int _bss_end__;
extern int __fini_array_end;
}
alias __data_start Data_Start;
alias _end Data_End;
}
alias void delegate( void*, void* ) scanFn;
}
/**
*
*/
extern (C) void rt_scanStaticData( scanFn scan )
{
version( Win32 )
{
scan( &Data_Start, &Data_End );
}
else version( linux )
{
//printf("scanning static data from %p to %p\n", &Data_Start, &Data_End);
scan( &Data_Start, &Data_End );
}
else
{
static assert( false, "Operating system not supported." );
}
}

208
runtime/internal/monitor.c Normal file
View 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

70
runtime/internal/qsort2.d Normal file
View File

@@ -0,0 +1,70 @@
/*
* Placed into Public Domain
* written by Walter Bright
* www.digitalmars.com
*
* This is a public domain version of qsort.d.
* All it does is call C's qsort(), but runs a little slower since
* it needs to synchronize a global variable.
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
//debug=qsort;
private import tango.stdc.stdlib;
struct Array
{
size_t length;
void* ptr;
}
private TypeInfo tiglobal;
extern (C) int cmp(void* p1, void* p2)
{
return tiglobal.compare(p1, p2);
}
extern (C) Array _adSort(Array a, TypeInfo ti)
{
synchronized
{
tiglobal = ti;
tango.stdc.stdlib.qsort(a.ptr, a.length, cast(size_t)ti.tsize(), &cmp);
}
return a;
}
unittest
{
debug(qsort) printf("array.sort.unittest()\n");
int a[] = new int[10];
a[0] = 23;
a[1] = 1;
a[2] = 64;
a[3] = 5;
a[4] = 6;
a[5] = 5;
a[6] = 17;
a[7] = 3;
a[8] = 0;
a[9] = -1;
a.sort;
for (int i = 0; i < a.length - 1; i++)
{
//printf("i = %d", i);
//printf(" %d %d\n", a[i], a[i + 1]);
assert(a[i] <= a[i + 1]);
}
}

425
runtime/internal/switch.d Normal file
View File

@@ -0,0 +1,425 @@
/*
* Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
/*
* Modified by Sean Kelly <sean@f4.ca> for use with Tango.
*/
private import tango.stdc.string;
//private import tango.stdc.stdio;
/******************************************************
* Support for switch statements switching on strings.
* Input:
* table[] sorted array of strings generated by compiler
* ca string to look up in table
* Output:
* result index of match in table[]
* -1 if not in table
*/
extern (C):
int _d_switch_string(char[][] table, char[] ca)
in
{
//printf("in _d_switch_string()\n");
assert(table.length >= 0);
assert(ca.length >= 0);
// Make sure table[] is sorted correctly
int j;
for (j = 1; j < table.length; j++)
{
size_t len1 = table[j - 1].length;
size_t len2 = table[j].length;
assert(len1 <= len2);
if (len1 == len2)
{
int ci;
ci = memcmp(table[j - 1].ptr, table[j].ptr, len1);
assert(ci < 0); // ci==0 means a duplicate
}
}
}
out (result)
{
int i;
int cj;
//printf("out _d_switch_string()\n");
if (result == -1)
{
// Not found
for (i = 0; i < table.length; i++)
{
if (table[i].length == ca.length)
{ cj = memcmp(table[i].ptr, ca.ptr, ca.length);
assert(cj != 0);
}
}
}
else
{
assert(0 <= result && result < table.length);
for (i = 0; 1; i++)
{
assert(i < table.length);
if (table[i].length == ca.length)
{
cj = memcmp(table[i].ptr, ca.ptr, ca.length);
if (cj == 0)
{
assert(i == result);
break;
}
}
}
}
}
body
{
//printf("body _d_switch_string(%.*s)\n", ca.length, ca.ptr);
size_t low;
size_t high;
size_t mid;
ptrdiff_t c;
char[] pca;
low = 0;
high = table.length;
version (none)
{
// Print table
printf("ca[] = '%s'\n", cast(char *)ca);
for (mid = 0; mid < high; mid++)
{
pca = table[mid];
printf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
}
}
if (high &&
ca.length >= table[0].length &&
ca.length <= table[high - 1].length)
{
// Looking for 0 length string, which would only be at the beginning
if (ca.length == 0)
return 0;
char c1 = ca[0];
// Do binary search
while (low < high)
{
mid = (low + high) >> 1;
pca = table[mid];
c = cast(ptrdiff_t)(ca.length - pca.length);
if (c == 0)
{
c = cast(ubyte)c1 - cast(ubyte)pca[0];
if (c == 0)
{
c = memcmp(ca.ptr, pca.ptr, ca.length);
if (c == 0)
{ //printf("found %d\n", mid);
return cast(int)mid;
}
}
}
if (c < 0)
{
high = mid;
}
else
{
low = mid + 1;
}
}
}
//printf("not found\n");
return -1; // not found
}
unittest
{
switch (cast(char []) "c")
{
case "coo":
default:
break;
}
}
/**********************************
* Same thing, but for wide chars.
*/
int _d_switch_ustring(wchar[][] table, wchar[] ca)
in
{
//printf("in _d_switch_ustring()\n");
assert(table.length >= 0);
assert(ca.length >= 0);
// Make sure table[] is sorted correctly
int j;
for (j = 1; j < table.length; j++)
{
size_t len1 = table[j - 1].length;
size_t len2 = table[j].length;
assert(len1 <= len2);
if (len1 == len2)
{
int c;
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * wchar.sizeof);
assert(c < 0); // c==0 means a duplicate
}
}
}
out (result)
{
int i;
int c;
//printf("out _d_switch_string()\n");
if (result == -1)
{
// Not found
for (i = 0; i < table.length; i++)
{
if (table[i].length == ca.length)
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
assert(c != 0);
}
}
}
else
{
assert(0 <= result && result < table.length);
for (i = 0; 1; i++)
{
assert(i < table.length);
if (table[i].length == ca.length)
{
c = memcmp(table[i].ptr, ca.ptr, ca.length * wchar.sizeof);
if (c == 0)
{
assert(i == result);
break;
}
}
}
}
}
body
{
//printf("body _d_switch_ustring()\n");
size_t low;
size_t high;
size_t mid;
ptrdiff_t c;
wchar[] pca;
low = 0;
high = table.length;
/*
// Print table
wprintf("ca[] = '%.*s'\n", ca);
for (mid = 0; mid < high; mid++)
{
pca = table[mid];
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
}
*/
// Do binary search
while (low < high)
{
mid = (low + high) >> 1;
pca = table[mid];
c = cast(ptrdiff_t)(ca.length - pca.length);
if (c == 0)
{
c = memcmp(ca.ptr, pca.ptr, ca.length * wchar.sizeof);
if (c == 0)
{ //printf("found %d\n", mid);
return cast(int)mid;
}
}
if (c < 0)
{
high = mid;
}
else
{
low = mid + 1;
}
}
//printf("not found\n");
return -1; // not found
}
unittest
{
switch (cast(wchar []) "c")
{
case "coo":
default:
break;
}
}
/**********************************
* Same thing, but for wide chars.
*/
int _d_switch_dstring(dchar[][] table, dchar[] ca)
in
{
//printf("in _d_switch_dstring()\n");
assert(table.length >= 0);
assert(ca.length >= 0);
// Make sure table[] is sorted correctly
int j;
for (j = 1; j < table.length; j++)
{
size_t len1 = table[j - 1].length;
size_t len2 = table[j].length;
assert(len1 <= len2);
if (len1 == len2)
{
int c;
c = memcmp(table[j - 1].ptr, table[j].ptr, len1 * dchar.sizeof);
assert(c < 0); // c==0 means a duplicate
}
}
}
out (result)
{
int i;
int c;
//printf("out _d_switch_string()\n");
if (result == -1)
{
// Not found
for (i = 0; i < table.length; i++)
{
if (table[i].length == ca.length)
{ c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
assert(c != 0);
}
}
}
else
{
assert(0 <= result && result < table.length);
for (i = 0; 1; i++)
{
assert(i < table.length);
if (table[i].length == ca.length)
{
c = memcmp(table[i].ptr, ca.ptr, ca.length * dchar.sizeof);
if (c == 0)
{
assert(i == result);
break;
}
}
}
}
}
body
{
//printf("body _d_switch_ustring()\n");
size_t low;
size_t high;
size_t mid;
ptrdiff_t c;
dchar[] pca;
low = 0;
high = table.length;
/*
// Print table
wprintf("ca[] = '%.*s'\n", ca);
for (mid = 0; mid < high; mid++)
{
pca = table[mid];
wprintf("table[%d] = %d, '%.*s'\n", mid, pca.length, pca);
}
*/
// Do binary search
while (low < high)
{
mid = (low + high) >> 1;
pca = table[mid];
c = cast(ptrdiff_t)(ca.length - pca.length);
if (c == 0)
{
c = memcmp(ca.ptr, pca.ptr, ca.length * dchar.sizeof);
if (c == 0)
{ //printf("found %d\n", mid);
return cast(int)mid;
}
}
if (c < 0)
{
high = mid;
}
else
{
low = mid + 1;
}
}
//printf("not found\n");
return -1; // not found
}
unittest
{
switch (cast(dchar []) "c")
{
case "coo":
default:
break;
}
}

View File

@@ -0,0 +1,95 @@
module typeinfo.ti_AC;
// Object[]
class TypeInfo_AC : TypeInfo_Array
{
hash_t getHash(void *p)
{ Object[] s = *cast(Object[]*)p;
hash_t hash = 0;
foreach (Object o; s)
{
if (o)
hash += o.toHash();
}
return hash;
}
int equals(void *p1, void *p2)
{
Object[] s1 = *cast(Object[]*)p1;
Object[] s2 = *cast(Object[]*)p2;
if (s1.length == s2.length)
{
for (size_t u = 0; u < s1.length; u++)
{ Object o1 = s1[u];
Object o2 = s2[u];
// Do not pass null's to Object.opEquals()
if (o1 is o2 ||
(!(o1 is null) && !(o2 is null) && o1.opEquals(o2)))
continue;
return 0;
}
return 1;
}
return 0;
}
int compare(void *p1, void *p2)
{
Object[] s1 = *cast(Object[]*)p1;
Object[] s2 = *cast(Object[]*)p2;
ptrdiff_t c;
c = cast(ptrdiff_t)s1.length - cast(ptrdiff_t)s2.length;
if (c == 0)
{
for (size_t u = 0; u < s1.length; u++)
{ Object o1 = s1[u];
Object o2 = s2[u];
if (o1 is o2)
continue;
// Regard null references as always being "less than"
if (o1)
{
if (!o2)
{ c = 1;
break;
}
c = o1.opCmp(o2);
if (c)
break;
}
else
{ c = -1;
break;
}
}
}
if (c < 0)
c = -1;
else
c = 1;
return cast(int)c;
}
size_t tsize()
{
return (Object[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(Object);
}
}

View 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 typeinfo.ti_Acdouble;
private import typeinfo.ti_cdouble;
// cdouble[]
class TypeInfo_Ar : TypeInfo_Array
{
char[] toString() { return "cdouble[]"; }
hash_t getHash(void *p)
{ cdouble[] s = *cast(cdouble[]*)p;
size_t len = s.length;
cdouble *str = s.ptr;
hash_t hash = 0;
while (len)
{
hash *= 9;
hash += (cast(uint *)str)[0];
hash += (cast(uint *)str)[1];
hash += (cast(uint *)str)[2];
hash += (cast(uint *)str)[3];
str++;
len--;
}
return hash;
}
int equals(void *p1, void *p2)
{
cdouble[] s1 = *cast(cdouble[]*)p1;
cdouble[] s2 = *cast(cdouble[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_r._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, void *p2)
{
cdouble[] s1 = *cast(cdouble[]*)p1;
cdouble[] s2 = *cast(cdouble[]*)p2;
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_r._compare(s1[u], s2[u]);
if (c)
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
size_t tsize()
{
return (cdouble[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(cdouble);
}
}

View File

@@ -0,0 +1,104 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module typeinfo.ti_Acfloat;
private import typeinfo.ti_cfloat;
// cfloat[]
class TypeInfo_Aq : TypeInfo_Array
{
char[] toString() { return "cfloat[]"; }
hash_t getHash(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;
}
int equals(void *p1, void *p2)
{
cfloat[] s1 = *cast(cfloat[]*)p1;
cfloat[] s2 = *cast(cfloat[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_q._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (cfloat[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(cfloat);
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module typeinfo.ti_Acreal;
private import typeinfo.ti_creal;
// creal[]
class TypeInfo_Ac : TypeInfo_Array
{
char[] toString() { return "creal[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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++)
{
int c = TypeInfo_c._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (creal[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(creal);
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, in both source and binary form, subject to the following
* restrictions:
*
* o The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* o Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
* o This notice may not be removed or altered from any source
* distribution.
*/
module typeinfo.ti_Adouble;
private import typeinfo.ti_double;
// double[]
class TypeInfo_Ad : TypeInfo_Array
{
char[] toString() { return "double[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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++)
{
int c = TypeInfo_d._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (double[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(double);
}
}
// idouble[]
class TypeInfo_Ap : TypeInfo_Ad
{
char[] toString() { return "idouble[]"; }
TypeInfo next()
{
return typeid(idouble);
}
}

View 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 typeinfo.ti_Afloat;
private import typeinfo.ti_float;
// float[]
class TypeInfo_Af : TypeInfo_Array
{
char[] toString() { return "float[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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++)
{
int c = TypeInfo_f._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (float[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(float);
}
}
// ifloat[]
class TypeInfo_Ao : TypeInfo_Af
{
char[] toString() { return "ifloat[]"; }
TypeInfo next()
{
return typeid(ifloat);
}
}

View File

@@ -0,0 +1,206 @@
module typeinfo.ti_Ag;
private import tango.stdc.string;
private import util.string;
// byte[]
class TypeInfo_Ag : TypeInfo_Array
{
char[] toString() { return "byte[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (byte[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(byte);
}
}
// ubyte[]
class TypeInfo_Ah : TypeInfo_Ag
{
char[] toString() { return "ubyte[]"; }
int compare(void *p1, void *p2)
{
char[] s1 = *cast(char[]*)p1;
char[] s2 = *cast(char[]*)p2;
return stringCompare(s1, s2);
}
TypeInfo next()
{
return typeid(ubyte);
}
}
// void[]
class TypeInfo_Av : TypeInfo_Ah
{
char[] toString() { return "void[]"; }
TypeInfo next()
{
return typeid(void);
}
}
// bool[]
class TypeInfo_Ab : TypeInfo_Ah
{
char[] toString() { return "bool[]"; }
TypeInfo next()
{
return typeid(bool);
}
}
// char[]
class TypeInfo_Aa : TypeInfo_Ag
{
char[] toString() { return "char[]"; }
hash_t getHash(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;
}
TypeInfo next()
{
return typeid(char);
}
}

View File

@@ -0,0 +1,119 @@
module typeinfo.ti_Aint;
private import tango.stdc.string;
// int[]
class TypeInfo_Ai : TypeInfo_Array
{
char[] toString() { return "int[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (int[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(int);
}
}
// uint[]
class TypeInfo_Ak : TypeInfo_Ai
{
char[] toString() { return "uint[]"; }
int compare(void *p1, 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;
}
TypeInfo next()
{
return typeid(uint);
}
}
// dchar[]
class TypeInfo_Aw : TypeInfo_Ak
{
char[] toString() { return "dchar[]"; }
TypeInfo next()
{
return typeid(dchar);
}
}

View File

@@ -0,0 +1,109 @@
module typeinfo.ti_Along;
private import tango.stdc.string;
// long[]
class TypeInfo_Al : TypeInfo_Array
{
char[] toString() { return "long[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (long[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(long);
}
}
// ulong[]
class TypeInfo_Am : TypeInfo_Al
{
char[] toString() { return "ulong[]"; }
int compare(void *p1, 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;
}
TypeInfo next()
{
return typeid(ulong);
}
}

View File

@@ -0,0 +1,117 @@
/*
* 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 typeinfo.ti_Areal;
private import typeinfo.ti_real;
// real[]
class TypeInfo_Ae : TypeInfo_Array
{
char[] toString() { return "real[]"; }
hash_t getHash(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;
}
int equals(void *p1, void *p2)
{
real[] s1 = *cast(real[]*)p1;
real[] s2 = *cast(real[]*)p2;
size_t len = s1.length;
if (len != s2.length)
return 0;
for (size_t u = 0; u < len; u++)
{
int c = TypeInfo_e._equals(s1[u], s2[u]);
if (c == 0)
return 0;
}
return 1;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (real[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(real);
}
}
// ireal[]
class TypeInfo_Aj : TypeInfo_Ae
{
char[] toString() { return "ireal[]"; }
TypeInfo next()
{
return typeid(ireal);
}
}

View File

@@ -0,0 +1,132 @@
module typeinfo.ti_Ashort;
private import tango.stdc.string;
// short[]
class TypeInfo_As : TypeInfo_Array
{
char[] toString() { return "short[]"; }
hash_t getHash(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;
}
int equals(void *p1, 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;
}
int compare(void *p1, 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;
}
size_t tsize()
{
return (short[]).sizeof;
}
uint flags()
{
return 1;
}
TypeInfo next()
{
return typeid(short);
}
}
// ushort[]
class TypeInfo_At : TypeInfo_As
{
char[] toString() { return "ushort[]"; }
int compare(void *p1, 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;
}
TypeInfo next()
{
return typeid(ushort);
}
}
// wchar[]
class TypeInfo_Au : TypeInfo_At
{
char[] toString() { return "wchar[]"; }
TypeInfo next()
{
return typeid(wchar);
}
}

View 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 typeinfo.ti_C;
// Object
class TypeInfo_C : TypeInfo
{
hash_t getHash(void *p)
{
Object o = *cast(Object*)p;
return o ? o.toHash() : 0;
}
int equals(void *p1, void *p2)
{
Object o1 = *cast(Object*)p1;
Object o2 = *cast(Object*)p2;
return o1 == o2;
}
int compare(void *p1, void *p2)
{
Object o1 = *cast(Object*)p1;
Object o2 = *cast(Object*)p2;
int c = 0;
// Regard null references as always being "less than"
if (!(o1 is o2))
{
if (o1)
{ if (!o2)
c = 1;
else
c = o1.opCmp(o2);
}
else
c = -1;
}
return c;
}
size_t tsize()
{
return Object.sizeof;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,39 @@
// byte
module typeinfo.ti_byte;
class TypeInfo_g : TypeInfo
{
char[] toString() { return "byte"; }
hash_t getHash(void *p)
{
return *cast(byte *)p;
}
int equals(void *p1, void *p2)
{
return *cast(byte *)p1 == *cast(byte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(byte *)p1 - *cast(byte *)p2;
}
size_t tsize()
{
return byte.sizeof;
}
void swap(void *p1, void *p2)
{
byte t;
t = *cast(byte *)p1;
*cast(byte *)p1 = *cast(byte *)p2;
*cast(byte *)p2 = t;
}
}

View File

@@ -0,0 +1,66 @@
// cdouble
module typeinfo.ti_cdouble;
class TypeInfo_r : TypeInfo
{
char[] toString() { return "cdouble"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
(cast(uint *)p)[2] + (cast(uint *)p)[3];
}
static int _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;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(cdouble *)p1, *cast(cdouble *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(cdouble *)p1, *cast(cdouble *)p2);
}
size_t tsize()
{
return cdouble.sizeof;
}
void swap(void *p1, void *p2)
{
cdouble t;
t = *cast(cdouble *)p1;
*cast(cdouble *)p1 = *cast(cdouble *)p2;
*cast(cdouble *)p2 = t;
}
void[] init()
{ static cdouble r;
return (cast(cdouble *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,65 @@
// cfloat
module typeinfo.ti_cfloat;
class TypeInfo_q : TypeInfo
{
char[] toString() { return "cfloat"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
}
static int _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;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(cfloat *)p1, *cast(cfloat *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(cfloat *)p1, *cast(cfloat *)p2);
}
size_t tsize()
{
return cfloat.sizeof;
}
void swap(void *p1, void *p2)
{
cfloat t;
t = *cast(cfloat *)p1;
*cast(cfloat *)p1 = *cast(cfloat *)p2;
*cast(cfloat *)p2 = t;
}
void[] init()
{ static cfloat r;
return (cast(cfloat *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,42 @@
module typeinfo.ti_char;
class TypeInfo_a : TypeInfo
{
char[] toString() { return "char"; }
hash_t getHash(void *p)
{
return *cast(char *)p;
}
int equals(void *p1, void *p2)
{
return *cast(char *)p1 == *cast(char *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(char *)p1 - *cast(char *)p2;
}
size_t tsize()
{
return char.sizeof;
}
void swap(void *p1, void *p2)
{
char t;
t = *cast(char *)p1;
*cast(char *)p1 = *cast(char *)p2;
*cast(char *)p2 = t;
}
void[] init()
{ static char c;
return (cast(char *)&c)[0 .. 1];
}
}

View File

@@ -0,0 +1,67 @@
// creal
module typeinfo.ti_creal;
class TypeInfo_c : TypeInfo
{
char[] toString() { return "creal"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] +
(cast(uint *)p)[2] + (cast(uint *)p)[3] +
(cast(uint *)p)[4];
}
static int _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;
}
int equals(void *p1, void *p2)
{
return _equals(*cast(creal *)p1, *cast(creal *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(creal *)p1, *cast(creal *)p2);
}
size_t tsize()
{
return creal.sizeof;
}
void swap(void *p1, void *p2)
{
creal t;
t = *cast(creal *)p1;
*cast(creal *)p1 = *cast(creal *)p2;
*cast(creal *)p2 = t;
}
void[] init()
{ static creal r;
return (cast(creal *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,44 @@
// dchar
module typeinfo.ti_dchar;
class TypeInfo_w : TypeInfo
{
char[] toString() { return "dchar"; }
hash_t getHash(void *p)
{
return *cast(dchar *)p;
}
int equals(void *p1, void *p2)
{
return *cast(dchar *)p1 == *cast(dchar *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(dchar *)p1 - *cast(dchar *)p2;
}
size_t tsize()
{
return dchar.sizeof;
}
void swap(void *p1, void *p2)
{
dchar t;
t = *cast(dchar *)p1;
*cast(dchar *)p1 = *cast(dchar *)p2;
*cast(dchar *)p2 = t;
}
void[] init()
{ static dchar c;
return (cast(dchar *)&c)[0 .. 1];
}
}

View File

@@ -0,0 +1,39 @@
// delegate
module typeinfo.ti_delegate;
alias void delegate(int) dg;
class TypeInfo_D : TypeInfo
{
hash_t getHash(void *p)
{ long l = *cast(long *)p;
return cast(uint)(l + (l >> 32));
}
int equals(void *p1, void *p2)
{
return *cast(dg *)p1 == *cast(dg *)p2;
}
size_t tsize()
{
return dg.sizeof;
}
void swap(void *p1, void *p2)
{
dg t;
t = *cast(dg *)p1;
*cast(dg *)p1 = *cast(dg *)p2;
*cast(dg *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,65 @@
// double
module typeinfo.ti_double;
class TypeInfo_d : TypeInfo
{
char[] toString() { return "double"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1];
}
static int _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);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(double *)p1, *cast(double *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(double *)p1, *cast(double *)p2);
}
size_t tsize()
{
return double.sizeof;
}
void swap(void *p1, void *p2)
{
double t;
t = *cast(double *)p1;
*cast(double *)p1 = *cast(double *)p2;
*cast(double *)p2 = t;
}
void[] init()
{ static double r;
return (cast(double *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,64 @@
// float
module typeinfo.ti_float;
class TypeInfo_f : TypeInfo
{
char[] toString() { return "float"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
static int _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);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(float *)p1, *cast(float *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(float *)p1, *cast(float *)p2);
}
size_t tsize()
{
return float.sizeof;
}
void swap(void *p1, void *p2)
{
float t;
t = *cast(float *)p1;
*cast(float *)p1 = *cast(float *)p2;
*cast(float *)p2 = t;
}
void[] init()
{ static float r;
return (cast(float *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,12 @@
// idouble
module typeinfo.ti_idouble;
private import typeinfo.ti_double;
class TypeInfo_p : TypeInfo_d
{
char[] toString() { return "idouble"; }
}

View File

@@ -0,0 +1,12 @@
// ifloat
module typeinfo.ti_ifloat;
private import typeinfo.ti_float;
class TypeInfo_o : TypeInfo_f
{
char[] toString() { return "ifloat"; }
}

View File

@@ -0,0 +1,43 @@
// int
module typeinfo.ti_int;
class TypeInfo_i : TypeInfo
{
char[] toString() { return "int"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
int equals(void *p1, void *p2)
{
return *cast(uint *)p1 == *cast(uint *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(int*) p1 < *cast(int*) p2)
return -1;
else if (*cast(int*) p1 > *cast(int*) p2)
return 1;
return 0;
}
size_t tsize()
{
return int.sizeof;
}
void swap(void *p1, void *p2)
{
int t;
t = *cast(int *)p1;
*cast(int *)p1 = *cast(int *)p2;
*cast(int *)p2 = t;
}
}

View File

@@ -0,0 +1,12 @@
// ireal
module typeinfo.ti_ireal;
private import typeinfo.ti_real;
class TypeInfo_j : TypeInfo_e
{
char[] toString() { return "ireal"; }
}

View File

@@ -0,0 +1,43 @@
// long
module typeinfo.ti_long;
class TypeInfo_l : TypeInfo
{
char[] toString() { return "long"; }
hash_t getHash(void *p)
{
return *cast(uint *)p + (cast(uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *cast(long *)p1 == *cast(long *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(long *)p1 < *cast(long *)p2)
return -1;
else if (*cast(long *)p1 > *cast(long *)p2)
return 1;
return 0;
}
size_t tsize()
{
return long.sizeof;
}
void swap(void *p1, void *p2)
{
long t;
t = *cast(long *)p1;
*cast(long *)p1 = *cast(long *)p2;
*cast(long *)p2 = t;
}
}

View File

@@ -0,0 +1,46 @@
// pointer
module typeinfo.ti_ptr;
class TypeInfo_P : TypeInfo
{
hash_t getHash(void *p)
{
return cast(uint)*cast(void* *)p;
}
int equals(void *p1, void *p2)
{
return *cast(void* *)p1 == *cast(void* *)p2;
}
int compare(void *p1, void *p2)
{
auto c = *cast(void* *)p1 - *cast(void* *)p2;
if (c < 0)
return -1;
else if (c > 0)
return 1;
return 0;
}
size_t tsize()
{
return (void*).sizeof;
}
void swap(void *p1, void *p2)
{
void* t;
t = *cast(void* *)p1;
*cast(void* *)p1 = *cast(void* *)p2;
*cast(void* *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,64 @@
// real
module typeinfo.ti_real;
class TypeInfo_e : TypeInfo
{
char[] toString() { return "real"; }
hash_t getHash(void *p)
{
return (cast(uint *)p)[0] + (cast(uint *)p)[1] + (cast(ushort *)p)[4];
}
static int _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);
}
int equals(void *p1, void *p2)
{
return _equals(*cast(real *)p1, *cast(real *)p2);
}
int compare(void *p1, void *p2)
{
return _compare(*cast(real *)p1, *cast(real *)p2);
}
size_t tsize()
{
return real.sizeof;
}
void swap(void *p1, void *p2)
{
real t;
t = *cast(real *)p1;
*cast(real *)p1 = *cast(real *)p2;
*cast(real *)p2 = t;
}
void[] init()
{ static real r;
return (cast(real *)&r)[0 .. 1];
}
}

View File

@@ -0,0 +1,39 @@
// short
module typeinfo.ti_short;
class TypeInfo_s : TypeInfo
{
char[] toString() { return "short"; }
hash_t getHash(void *p)
{
return *cast(short *)p;
}
int equals(void *p1, void *p2)
{
return *cast(short *)p1 == *cast(short *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(short *)p1 - *cast(short *)p2;
}
size_t tsize()
{
return short.sizeof;
}
void swap(void *p1, void *p2)
{
short t;
t = *cast(short *)p1;
*cast(short *)p1 = *cast(short *)p2;
*cast(short *)p2 = t;
}
}

View File

@@ -0,0 +1,43 @@
// ubyte
module typeinfo.ti_ubyte;
class TypeInfo_h : TypeInfo
{
char[] toString() { return "ubyte"; }
hash_t getHash(void *p)
{
return *cast(ubyte *)p;
}
int equals(void *p1, void *p2)
{
return *cast(ubyte *)p1 == *cast(ubyte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(ubyte *)p1 - *cast(ubyte *)p2;
}
size_t tsize()
{
return ubyte.sizeof;
}
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
{
char[] toString() { return "bool"; }
}

View File

@@ -0,0 +1,43 @@
// uint
module typeinfo.ti_uint;
class TypeInfo_k : TypeInfo
{
char[] toString() { return "uint"; }
hash_t getHash(void *p)
{
return *cast(uint *)p;
}
int equals(void *p1, void *p2)
{
return *cast(uint *)p1 == *cast(uint *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(uint*) p1 < *cast(uint*) p2)
return -1;
else if (*cast(uint*) p1 > *cast(uint*) p2)
return 1;
return 0;
}
size_t tsize()
{
return uint.sizeof;
}
void swap(void *p1, void *p2)
{
int t;
t = *cast(uint *)p1;
*cast(uint *)p1 = *cast(uint *)p2;
*cast(uint *)p2 = t;
}
}

View File

@@ -0,0 +1,43 @@
// ulong
module typeinfo.ti_ulong;
class TypeInfo_m : TypeInfo
{
char[] toString() { return "ulong"; }
hash_t getHash(void *p)
{
return *cast(uint *)p + (cast(uint *)p)[1];
}
int equals(void *p1, void *p2)
{
return *cast(ulong *)p1 == *cast(ulong *)p2;
}
int compare(void *p1, void *p2)
{
if (*cast(ulong *)p1 < *cast(ulong *)p2)
return -1;
else if (*cast(ulong *)p1 > *cast(ulong *)p2)
return 1;
return 0;
}
size_t tsize()
{
return ulong.sizeof;
}
void swap(void *p1, void *p2)
{
ulong t;
t = *cast(ulong *)p1;
*cast(ulong *)p1 = *cast(ulong *)p2;
*cast(ulong *)p2 = t;
}
}

View File

@@ -0,0 +1,39 @@
// ushort
module typeinfo.ti_ushort;
class TypeInfo_t : TypeInfo
{
char[] toString() { return "ushort"; }
hash_t getHash(void *p)
{
return *cast(ushort *)p;
}
int equals(void *p1, void *p2)
{
return *cast(ushort *)p1 == *cast(ushort *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(ushort *)p1 - *cast(ushort *)p2;
}
size_t tsize()
{
return ushort.sizeof;
}
void swap(void *p1, void *p2)
{
ushort t;
t = *cast(ushort *)p1;
*cast(ushort *)p1 = *cast(ushort *)p2;
*cast(ushort *)p2 = t;
}
}

View File

@@ -0,0 +1,43 @@
// void
module typeinfo.ti_void;
class TypeInfo_v : TypeInfo
{
char[] toString() { return "void"; }
hash_t getHash(void *p)
{
assert(0);
}
int equals(void *p1, void *p2)
{
return *cast(byte *)p1 == *cast(byte *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(byte *)p1 - *cast(byte *)p2;
}
size_t tsize()
{
return void.sizeof;
}
void swap(void *p1, void *p2)
{
byte t;
t = *cast(byte *)p1;
*cast(byte *)p1 = *cast(byte *)p2;
*cast(byte *)p2 = t;
}
uint flags()
{
return 1;
}
}

View File

@@ -0,0 +1,43 @@
module typeinfo.ti_wchar;
class TypeInfo_u : TypeInfo
{
char[] toString() { return "wchar"; }
hash_t getHash(void *p)
{
return *cast(wchar *)p;
}
int equals(void *p1, void *p2)
{
return *cast(wchar *)p1 == *cast(wchar *)p2;
}
int compare(void *p1, void *p2)
{
return *cast(wchar *)p1 - *cast(wchar *)p2;
}
size_t tsize()
{
return wchar.sizeof;
}
void swap(void *p1, void *p2)
{
wchar t;
t = *cast(wchar *)p1;
*cast(wchar *)p1 = *cast(wchar *)p2;
*cast(wchar *)p2 = t;
}
void[] init()
{ static wchar c;
return (cast(wchar *)&c)[0 .. 1];
}
}

View File

@@ -0,0 +1,86 @@
/*******************************************************************************
copyright: Copyright (c) 2004 Tango group. All rights reserved
license: BSD style: $(LICENSE)
version: Initial release: July 2006
Various low-level console oriented utilities
*******************************************************************************/
module util.console;
private import util.string;
version (Win32)
{
private extern (Windows) int GetStdHandle (int);
private extern (Windows) int WriteFile (int, char*, int, int*, void*);
}
else
version (Posix)
{
private extern (C) ptrdiff_t write (int, void*, size_t);
}
/+
// emit a char[] to the console. Note that Win32 does not handle utf8, but
// then neither does fprintf (stderr). This will handle redirection though.
// May need to remedy the utf8 issue
int console (char[] s)
{
version (Win32)
{
int count;
if (WriteFile (GetStdHandle(0xfffffff5), s.ptr, s.length, &count, null))
return count;
return -1;
}
else
version (Posix)
{
return write (2, s.ptr, s.length);
}
}
// emit an integer to the console
int console (uint i)
{
char[10] tmp = void;
return console (intToUtf8 (tmp, i));
}
+/
struct Console
{
Console opCall (char[] s)
{
version (Win32)
{
int count;
WriteFile (GetStdHandle(0xfffffff5), s.ptr, s.length, &count, null);
}
else
version (Posix)
{
write (2, s.ptr, s.length);
}
return *this;
}
// emit an integer to the console
Console opCall (size_t i)
{
char[25] tmp = void;
return console (intToUtf8 (tmp, i));
}
}
Console console;

View 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 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'));
}

View File

@@ -0,0 +1,50 @@
/*******************************************************************************
copyright: Copyright (c) 2004 Tango group. All rights reserved
license: BSD style: $(LICENSE)
version: Initial release: July 2006
Various char[] utilities
*******************************************************************************/
module util.string;
private import tango.stdc.string;
// convert uint to char[], within the given buffer
// Returns a valid slice of the populated buffer
char[] intToUtf8 (char[] tmp, size_t val)
in {
assert (tmp.length > 20, "atoi buffer should be 20 or more chars wide");
}
body
{
char* p = tmp.ptr + tmp.length;
do {
*--p = (val % 10) + '0';
} while (val /= 10);
return tmp [cast(size_t)(p - tmp.ptr) .. $];
}
// function to compare two strings
int stringCompare (char[] s1, char[] s2)
{
auto len = s1.length;
if (s2.length < len)
len = s2.length;
int result = memcmp(s1.ptr, s2.ptr, len);
if (result == 0)
result = cast(int)s1.length - cast(int)s2.length;
return result;
}

851
runtime/internal/util/utf.d Normal file
View File

@@ -0,0 +1,851 @@
// utf.d
/*
* 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.
*/
// Description of UTF-8 at:
// http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
// http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335
module util.utf;
extern (C) void onUnicodeError( char[] msg, size_t idx );
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);
}
/* This array gives the length of a UTF-8 sequence indexed by the value
* of the leading byte. An FF represents an illegal starting value of
* a UTF-8 sequence.
* FF is used instead of 0 to avoid having loops hang.
*/
ubyte[256] UTF8stride =
[
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,
];
uint stride(char[] s, size_t i)
{
return UTF8stride[s[i]];
}
uint stride(wchar[] s, size_t i)
{ uint u = s[i];
return 1 + (u >= 0xD800 && u <= 0xDBFF);
}
uint stride(dchar[] s, size_t i)
{
return 1;
}
/*******************************************
* Given an index into an array of char's,
* and assuming that index is at the start of a UTF character,
* determine the number of UCS characters up to that index.
*/
size_t toUCSindex(char[] s, size_t i)
{
size_t n;
size_t j;
size_t stride;
for (j = 0; j < i; j += stride)
{
stride = UTF8stride[s[j]];
if (stride == 0xFF)
goto Lerr;
n++;
}
if (j > i)
{
Lerr:
onUnicodeError("invalid UTF-8 sequence", j);
}
return n;
}
size_t toUCSindex(wchar[] s, size_t i)
{
size_t n;
size_t j;
for (j = 0; j < i; )
{ uint u = s[j];
j += 1 + (u >= 0xD800 && u <= 0xDBFF);
n++;
}
if (j > i)
{
Lerr:
onUnicodeError("invalid UTF-16 sequence", j);
}
return n;
}
size_t toUCSindex(dchar[] s, size_t i)
{
return i;
}
/******************************************
* Given a UCS index into an array of characters, return the UTF index.
*/
size_t toUTFindex(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;
}
size_t toUTFindex(wchar[] s, size_t n)
{
size_t i;
while (n--)
{ wchar u = s[i];
i += 1 + (u >= 0xD800 && u <= 0xDBFF);
}
return i;
}
size_t toUTFindex(dchar[] s, size_t n)
{
return n;
}
/* =================== Decode ======================= */
dchar decode(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 char[] s1 = "abcd";
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 char[] s2 = "\xC2\xA9";
i = 0;
c = decode(s2, i);
assert(c == cast(dchar)'\u00A9');
assert(i == 2);
static char[] s3 = "\xE2\x89\xA0";
i = 0;
c = decode(s3, i);
assert(c == cast(dchar)'\u2260');
assert(i == 3);
static char[][] s4 =
[ "\xE2\x89", // 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);
}
}
/********************************************************/
dchar decode(wchar[] s, inout size_t idx)
in
{
assert(idx >= 0 && idx < s.length);
}
out (result)
{
assert(isValidDchar(result));
}
body
{
char[] 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
}
/********************************************************/
dchar decode(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 ======================= */
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";
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");
}
/********************************************************/
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;
}
void encode(inout dchar[] s, dchar c)
in
{
assert(isValidDchar(c));
}
body
{
s ~= c;
}
/* =================== Validation ======================= */
void validate(char[] s)
{
size_t len = s.length;
size_t i;
for (i = 0; i < len; )
{
decode(s, i);
}
}
void validate(wchar[] s)
{
size_t len = s.length;
size_t i;
for (i = 0; i < len; )
{
decode(s, i);
}
}
void validate(dchar[] s)
{
size_t len = s.length;
size_t i;
for (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);
}
char[] toUTF8(char[] s)
in
{
validate(s);
}
body
{
return s;
}
char[] toUTF8(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 r;
}
char[] toUTF8(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 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];
}
}
wchar[] toUTF16(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 r;
}
wchar* toUTF16z(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;
}
wchar[] toUTF16(wchar[] s)
in
{
validate(s);
}
body
{
return s;
}
wchar[] toUTF16(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 r;
}
/* =================== Conversion to UTF32 ======================= */
dchar[] toUTF32(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 r[0 .. j];
}
dchar[] toUTF32(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 r[0 .. j];
}
dchar[] toUTF32(dchar[] s)
in
{
validate(s);
}
body
{
return s;
}
/* ================================ tests ================================== */
unittest
{
debug(utf) printf("utf.toUTF.unittest\n");
char[] c;
wchar[] w;
dchar[] d;
c = "hello";
w = toUTF16(c);
assert(w == "hello");
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(wchar[])"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");
}

View File

@@ -0,0 +1,154 @@
# Makefile to build the common D runtime library for LLVM
# 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=libtango-cc-tango.a
LIB_MASK=libtango-cc-tango*.a
LIB_TARGET_C=libtango-cc-c-tango.a
LIB_MASK_C=libtango-cc-c-tango*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
ADD_CFLAGS=
ADD_DFLAGS=
#CFLAGS=-O3 $(ADD_CFLAGS)
CFLAGS=-g $(ADD_CFLAGS)
#DFLAGS=-release -O3 -inline -w $(ADD_DFLAGS)
DFLAGS=-g -w -noasm $(ADD_DFLAGS)
#TFLAGS=-O3 -inline -w $(ADD_DFLAGS)
TFLAGS=-g -w -noasm $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=gcc
LC=llvm-ar rsv
CLC=ar rsv
DC=llvmdc
LLC=llvm-as
INC_DEST=../../../tango
LIB_DEST=..
DOC_DEST=../../../doc/tango
.SUFFIXES: .s .S .c .cpp .d .ll .html .o .bc
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.bc:
$(DC) -c $(DFLAGS) -Hf$*.di $< -of$@
# $(DC) -c $(DFLAGS) $< -of$@
.ll.bc:
$(LLC) -f -o=$@ $<
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html tango.ddoc $<
targets : lib doc
all : lib doc
tango : lib
lib : tango.lib tango.clib
doc : tango.doc
######################################################
OBJ_CORE= \
core/BitManip.bc \
core/Exception.bc \
core/Memory.bc \
core/Runtime.bc \
core/Thread.bc
# core/ThreadASM.o
OBJ_STDC= \
stdc/wrap.o
# stdc/wrap.bc
OBJ_STDC_POSIX= \
stdc/posix/pthread_darwin.o
ALL_OBJS= \
$(OBJ_CORE)
# $(OBJ_STDC)
# $(OBJ_STDC_POSIX)
######################################################
DOC_CORE= \
core/BitManip.html \
core/Exception.html \
core/Memory.html \
core/Runtime.html \
core/Thread.html
ALL_DOCS=
######################################################
tango.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
tango.clib : $(LIB_TARGET_C)
$(LIB_TARGET_C) : $(OBJ_STDC)
$(RM) $@
$(CLC) $@ $(OBJ_STDC)
tango.doc : $(ALL_DOCS)
echo Documentation generated.
######################################################
### stdc/posix
#stdc/posix/pthread_darwin.o : stdc/posix/pthread_darwin.d
# $(DC) -c $(DFLAGS) stdc/posix/pthread_darwin.d -of$@
######################################################
clean :
find . -name "*.di" | xargs $(RM)
$(RM) $(ALL_OBJS)
$(RM) $(OBJ_STDC)
$(RM) $(ALL_DOCS)
find . -name "$(LIB_MASK)" | xargs $(RM)
find . -name "$(LIB_MASK_C)" | 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)/{} \;
find . -name "$(LIB_MASK_C)" -exec cp -f {} $(LIB_DEST)/{} \;

View File

@@ -0,0 +1,100 @@
# Makefile to build the garbage collector D library for LLVMDC
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the garbage collector library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-gc-basic.a
LIB_MASK=libtango-gc-basic*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
ADD_CFLAGS=
ADD_DFLAGS=
#CFLAGS=-O3 $(ADD_CFLAGS)
CFLAGS=-g $(ADD_CFLAGS)
#DFLAGS=-release -O3 -inline -w -nofloat $(ADD_DFLAGS)
DFLAGS=-g -w -nofloat $(ADD_DFLAGS)
#TFLAGS=-O3 -inline -w -nofloat $(ADD_DFLAGS)
TFLAGS=-g -w -nofloat $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=gcc
LC=llvm-ar rsv
DC=llvmdc
LIB_DEST=..
.SUFFIXES: .s .S .c .cpp .d .html .o .bc
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.bc:
$(DC) -c $(DFLAGS) $< -of$@
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
targets : lib doc
all : lib doc
lib : basic.lib
doc : basic.doc
######################################################
ALL_OBJS= \
gc.bc \
gcalloc.bc \
gcbits.bc \
gcstats.bc \
gcx.bc
######################################################
ALL_DOCS=
######################################################
basic.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
basic.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)/.

View File

@@ -0,0 +1,96 @@
# Makefile to build the garbage collector D library for Posix
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the garbage collector library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-gc-stub.a
LIB_MASK=libtango-gc-stub*.a
CP=cp -f
RM=rm -f
MD=mkdir -p
ADD_CFLAGS=
ADD_DFLAGS=
#CFLAGS=-O3 $(ADD_CFLAGS)
CFLAGS=-g $(ADD_CFLAGS)
#DFLAGS=-release -O3 -inline -w $(ADD_DFLAGS)
DFLAGS=-g $(ADD_DFLAGS)
#TFLAGS=-O3 -inline $(ADD_DFLAGS)
TFLAGS=-g $(ADD_DFLAGS)
DOCFLAGS=-version=DDoc
CC=gcc
LC=llvm-ar rsv
DC=llvmdc
LIB_DEST=..
.SUFFIXES: .s .S .c .cpp .d .html .o .bc
.s.o:
$(CC) -c $(CFLAGS) $< -o$@
.S.o:
$(CC) -c $(CFLAGS) $< -o$@
.c.o:
$(CC) -c $(CFLAGS) $< -o$@
.cpp.o:
g++ -c $(CFLAGS) $< -o$@
.d.bc:
$(DC) -c $(DFLAGS) $< -of$@
.d.html:
$(DC) -c -o- $(DOCFLAGS) -Df$*.html $<
# $(DC) -c -o- $(DOCFLAGS) -Df$*.html dmd.ddoc $<
targets : lib doc
all : lib doc
lib : stub.lib
doc : stub.doc
######################################################
ALL_OBJS= \
gc.bc
######################################################
ALL_DOCS=
######################################################
stub.lib : $(LIB_TARGET)
$(LIB_TARGET) : $(ALL_OBJS)
$(RM) $@
$(LC) $@ $(ALL_OBJS)
stub.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)/.

View File

@@ -0,0 +1,104 @@
# Makefile to build the composite D runtime library for Linux
# Designed to work with GNU make
# Targets:
# make
# Same as make all
# make lib
# Build the runtime library
# make doc
# Generate documentation
# make clean
# Delete unneeded files created by build process
LIB_TARGET=libtango-base-llvmdc.a
LIB_MASK=libtango-base-llvmdc*.a
LIB_TARGET_C=libtango-base-c-llvmdc.a
LIB_MASK_C=libtango-base-c-llvmdc*.a
LIB_NAME_NATIVE=libtango-base-llvmdc-native
LIB_TARGET_NATIVE=$(LIB_NAME_NATIVE).a
DIR_CC=./common/tango
DIR_RT=../../runtime/internal
DIR_GC=./gc/basic
#DIR_GC=./gc/stub
CP=cp -f
RM=rm -f
MD=mkdir -p
CC=gcc
LC=llvm-ar rsv
CLC=ar rsv
DC=llvmdc
LLVMLINK=llvm-link
LLC=llc
ADD_CFLAGS=
#ADD_DFLAGS=
ADD_DFLAGS=-I`pwd`/common -I`pwd`/.. -I`pwd`/compiler/llvmdc
targets : nativelib doc
all : nativelib lib doc
######################################################
ALL_OBJS=
######################################################
ALL_DOCS=
######################################################
lib : $(ALL_OBJS)
make -C $(DIR_CC) -fllvmdc.mak lib DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)"
make -C $(DIR_RT) -fllvmdc.mak lib
make -C $(DIR_GC) -fllvmdc.mak lib DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)"
find . -name $(LIB_MASK) | xargs $(RM)
$(LC) $(LIB_TARGET) `find $(DIR_CC) -name "*.bc" | xargs echo`
$(LC) $(LIB_TARGET) `find $(DIR_RT) -name "*.bc" | xargs echo`
$(LC) $(LIB_TARGET) `find $(DIR_GC) -name "*.bc" | xargs echo`
$(CLC) $(LIB_TARGET_C) `find $(DIR_CC) -name "*.o" | xargs echo`
$(CLC) $(LIB_TARGET_C) `find $(DIR_RT) -name "*.o" | xargs echo`
nativelib: $(ALL_OBJS)
make -C $(DIR_CC) -fllvmdc.mak lib DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)"
make -C $(DIR_RT) -fllvmdc.mak lib
make -C $(DIR_GC) -fllvmdc.mak lib DC=$(DC) ADD_DFLAGS="$(ADD_DFLAGS)" ADD_CFLAGS="$(ADD_CFLAGS)"
$(RM) $(LIB_NAME_NATIVE)*
# first link all bcs together to a single bitcode file
$(LLVMLINK) -o=$(LIB_NAME_NATIVE)-llvm.bc `find $(DIR_CC) $(DIR_RT) $(DIR_GC) -name "*.bc"`
# then compile to assembler
$(LLC) -o=$(LIB_NAME_NATIVE)-llvm.s $(LIB_NAME_NATIVE)-llvm.bc
# assemble native code
$(CC) -c -o $(LIB_NAME_NATIVE)-llvm.o $(LIB_NAME_NATIVE)-llvm.s
# make an archive containing it and the other native object files
$(CLC) $(LIB_TARGET_NATIVE) $(LIB_NAME_NATIVE)-llvm.o `find $(DIR_CC) $(DIR_RT) -name "*.o"`
doc : $(ALL_DOCS)
make -C $(DIR_CC) -fllvmdc.mak doc
make -C $(DIR_RT) -fllvmdc.mak doc
make -C $(DIR_GC) -fllvmdc.mak doc
######################################################
clean :
find . -name "*.di" | xargs $(RM)
$(RM) $(ALL_OBJS)
$(RM) $(ALL_DOCS)
make -C $(DIR_CC) -fllvmdc.mak clean
make -C $(DIR_RT) -fllvmdc.mak clean
make -C $(DIR_GC) -fllvmdc.mak clean
$(RM) $(LIB_MASK)
$(RM) $(LIB_MASK_C)
$(RM) $(LIB_NAME_NATIVE)*
install :
make -C $(DIR_CC) -fllvmdc.mak install
make -C $(DIR_RT) -fllvmdc.mak install
make -C $(DIR_GC) -fllvmdc.mak install
$(CP) $(LIB_MASK) $(LIB_DEST)/.
$(CP) $(LIB_MASK_C) $(LIB_DEST)/.

672
runtime/llvmdc.diff Normal file
View File

@@ -0,0 +1,672 @@
Index: object.di
===================================================================
--- object.di (revision 3819)
+++ object.di (working copy)
@@ -150,6 +150,9 @@
void function() dtor;
void function() unitTest;
+ void* xgetMembers;
+ void function() ictor;
+
static int opApply( int delegate( inout ModuleInfo ) );
}
Index: lib/common/tango/core/BitManip.d
===================================================================
--- lib/common/tango/core/BitManip.d (revision 3819)
+++ lib/common/tango/core/BitManip.d (working copy)
@@ -171,6 +171,10 @@
*/
uint outpl( uint port_address, uint value );
}
+else version( LLVMDC )
+{
+ public import llvmdc.bitmanip;
+}
else
{
public import std.intrinsic;
Index: lib/common/tango/core/Thread.d
===================================================================
--- lib/common/tango/core/Thread.d (revision 3819)
+++ lib/common/tango/core/Thread.d (working copy)
@@ -244,10 +244,33 @@
}
body
{
- version( D_InlineAsm_X86 )
+ version( LLVMDC )
{
+ // put registers on the stack
+ version(D_InlineAsm_X86)
+ {
+ uint _eax, _ecx, _edx, _ebx, _esp, _ebp, _esi, _edi;
asm
{
+ mov _eax, EAX;
+ mov _ecx, ECX;
+ mov _edx, EDX;
+ mov _ebx, EBX;
+ mov _esp, ESP;
+ mov _ebp, EBP;
+ mov _esi, ESI;
+ mov _edi, EDI;
+ }
+ }
+ else
+ {
+ // FIXME
+ }
+ }
+ else version( D_InlineAsm_X86 )
+ {
+ asm
+ {
pushad;
}
}
@@ -297,8 +320,12 @@
}
}
- version( D_InlineAsm_X86 )
+ version( LLVMDC )
{
+ // nothing to do
+ }
+ else version( D_InlineAsm_X86 )
+ {
asm
{
popad;
@@ -2266,8 +2293,12 @@
private
{
- version( D_InlineAsm_X86 )
+ version( LLVMDC )
{
+
+ }
+ else version( D_InlineAsm_X86 )
+ {
version( X86_64 )
{
Index: lib/gc/basic/gcx.d
===================================================================
--- lib/gc/basic/gcx.d (revision 3819)
+++ lib/gc/basic/gcx.d (working copy)
@@ -2178,6 +2178,28 @@
__builtin_unwind_init();
sp = & sp;
}
+ else version(LLVMDC)
+ {
+ version(D_InlineAsm_X86)
+ {
+ uint _eax, _ecx, _edx, _ebx, _ebp, _esi, _edi;
+ asm
+ {
+ mov _eax, EAX;
+ mov _ecx, ECX;
+ mov _edx, EDX;
+ mov _ebx, EBX;
+ mov _ebp, EBP;
+ mov _esi, ESI;
+ mov _edi, EDI;
+ mov sp, ESP;
+ }
+ }
+ else
+ {
+ // FIXME
+ }
+ }
else
{
asm
@@ -2191,6 +2213,10 @@
{
// nothing to do
}
+ else version(LLVMDC)
+ {
+ // nothing to do
+ }
else
{
asm
Index: lib/gc/basic/gcbits.d
===================================================================
--- lib/gc/basic/gcbits.d (revision 3819)
+++ lib/gc/basic/gcbits.d (working copy)
@@ -39,6 +39,10 @@
{
// use the unoptimized version
}
+else version(LLVMDC)
+{
+ // ditto
+}
else version (D_InlineAsm_X86)
{
version = Asm86;
Index: tango/text/convert/Layout.d
===================================================================
--- tango/text/convert/Layout.d (revision 3819)
+++ tango/text/convert/Layout.d (working copy)
@@ -47,6 +47,12 @@
alias void* Arg;
alias va_list ArgList;
}
+else version(LLVMDC)
+ {
+ private import tango.core.Vararg;
+ alias void* Arg;
+ alias va_list ArgList;
+ }
else
{
alias void* Arg;
@@ -197,9 +203,18 @@
assert (formatStr, "null format specifier");
assert (arguments.length < 64, "too many args in Layout.convert");
- version (GNU)
+ version (LLVMDC)
{
Arg[64] arglist = void;
+ foreach (i, arg; arguments)
+ {
+ arglist[i] = args;
+ args += (arg.tsize + size_t.sizeof - 1) & ~ (size_t.sizeof - 1);
+ }
+ }
+ else version (GNU)
+ {
+ Arg[64] arglist = void;
int[64] intargs = void;
byte[64] byteargs = void;
long[64] longargs = void;
Index: tango/core/Vararg.d
===================================================================
--- tango/core/Vararg.d (revision 3819)
+++ tango/core/Vararg.d (working copy)
@@ -15,6 +15,10 @@
{
public import std.stdarg;
}
+else version( LLVMDC )
+{
+ public import llvmdc.vararg;
+}
else
{
/**
Index: tango/math/Math.d
===================================================================
--- tango/math/Math.d (revision 3819)
+++ tango/math/Math.d (working copy)
@@ -76,7 +76,77 @@
version = DigitalMars_D_InlineAsm_X86;
}
}
+else version(LLVMDC)
+{
+ private
+ {
+ pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f32")
+ float llvm_sqrt(float);
+ pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
+ double llvm_sqrt(double);
+
+ version(LLVM_X86_FP80)
+ {
+ alias tango.stdc.math.tanl llvm_tan;
+ alias tango.stdc.math.acosl llvm_acos;
+ alias tango.stdc.math.asinl llvm_asin;
+ alias tango.stdc.math.atanl llvm_atan;
+ alias tango.stdc.math.atan2l llvm_atan2;
+ alias tango.stdc.math.coshl llvm_cosh;
+ alias tango.stdc.math.sinhl llvm_sinh;
+ alias tango.stdc.math.tanhl llvm_tanh;
+ alias tango.stdc.math.cbrtl llvm_cbrt;
+ alias tango.stdc.math.expl llvm_exp;
+ alias tango.stdc.math.exp1ml llvm_exp1m;
+ alias tango.stdc.math.exp2l llvm_exp2;
+ alias tango.stdc.math.logl llvm_log;
+ alias tango.stdc.math.log1pl llvm_log1p;
+ alias tango.stdc.math.log2l llvm_log2;
+ alias tango.stdc.math.log10l llvm_log10;
+ alias tango.stdc.math.powl llvm_pow;
+ alias tango.stdc.math.lrintl llvm_lrint;
+ alias tango.stdc.math.llrintl llvm_llrint;
+
+ pragma(LLVM_internal, "intrinsic", "llvm.cos.f80")
+ real llvm_cos(real);
+ pragma(LLVM_internal, "intrinsic", "llvm.sin.f80")
+ real llvm_sin(real);
+ pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f80")
+ real llvm_sqrt(real);
+ }
+ else
+ {
+ alias tango.stdc.math.tan llvm_tan;
+ alias tango.stdc.math.acos llvm_acos;
+ alias tango.stdc.math.asin llvm_asin;
+ alias tango.stdc.math.atan llvm_atan;
+ alias tango.stdc.math.atan2 llvm_atan2;
+ alias tango.stdc.math.cosh llvm_cosh;
+ alias tango.stdc.math.sinh llvm_sinh;
+ alias tango.stdc.math.tanh llvm_tanh;
+ alias tango.stdc.math.cbrt llvm_cbrt;
+ alias tango.stdc.math.exp llvm_exp;
+ alias tango.stdc.math.exp1m llvm_exp1m;
+ alias tango.stdc.math.exp2 llvm_exp2;
+ alias tango.stdc.math.log llvm_log;
+ alias tango.stdc.math.log1p llvm_log1p;
+ alias tango.stdc.math.log2 llvm_log2;
+ alias tango.stdc.math.log10 llvm_log10;
+ alias tango.stdc.math.pow llvm_pow;
+ alias tango.stdc.math.lrint llvm_lrint;
+ alias tango.stdc.math.llrint llvm_llrint;
+
+ pragma(LLVM_internal, "intrinsic", "llvm.cos.f64")
+ real llvm_cos(real);
+ pragma(LLVM_internal, "intrinsic", "llvm.sin.f64")
+ real llvm_sin(real);
+ pragma(LLVM_internal, "intrinsic", "llvm.sqrt.f64")
+ real llvm_sqrt(real);
+ }
+ }
+}
+
/*
* Constants
*/
@@ -300,6 +370,10 @@
*/
real cos(real x) /* intrinsic */
{
+ version(LLVMDC)
+ {
+ return llvm_cos(x);
+ }
version(D_InlineAsm_X86)
{
asm
@@ -335,6 +409,10 @@
*/
real sin(real x) /* intrinsic */
{
+ version(LLVMDC)
+ {
+ return llvm_sin(x);
+ }
version(D_InlineAsm_X86)
{
asm
@@ -374,6 +452,9 @@
{
version (GNU) {
return tanl(x);
+ }
+ else version(LLVMDC) {
+ return llvm_tan(x);
} else {
asm
{
@@ -576,7 +657,14 @@
*/
real acos(real x)
{
- return tango.stdc.math.acosl(x);
+ version(LLVMDC)
+ {
+ return llvm_acos(x);
+ }
+ else
+ {
+ return tango.stdc.math.acosl(x);
+ }
}
debug(UnitTest) {
@@ -599,7 +687,14 @@
*/
real asin(real x)
{
- return tango.stdc.math.asinl(x);
+ version(LLVMDC)
+ {
+ return llvm_asin(x);
+ }
+ else
+ {
+ return tango.stdc.math.asinl(x);
+ }
}
debug(UnitTest) {
@@ -621,7 +716,14 @@
*/
real atan(real x)
{
- return tango.stdc.math.atanl(x);
+ version(LLVMDC)
+ {
+ return llvm_atan(x);
+ }
+ else
+ {
+ return tango.stdc.math.atanl(x);
+ }
}
debug(UnitTest) {
@@ -658,7 +760,14 @@
*/
real atan2(real y, real x)
{
- return tango.stdc.math.atan2l(y,x);
+ version(LLVMDC)
+ {
+ return llvm_atan2(x);
+ }
+ else
+ {
+ return tango.stdc.math.atan2l(x);
+ }
}
debug(UnitTest) {
@@ -707,7 +816,14 @@
*/
real cosh(real x)
{
- return tango.stdc.math.coshl(x);
+ version(LLVMDC)
+ {
+ return llvm_cosh(x);
+ }
+ else
+ {
+ return tango.stdc.math.coshl(x);
+ }
}
debug(UnitTest) {
@@ -728,7 +844,14 @@
*/
real sinh(real x)
{
- return tango.stdc.math.sinhl(x);
+ version(LLVMDC)
+ {
+ return llvm_sinh(x);
+ }
+ else
+ {
+ return tango.stdc.math.sinhl(x);
+ }
}
debug(UnitTest) {
@@ -749,7 +872,14 @@
*/
real tanh(real x)
{
- return tango.stdc.math.tanhl(x);
+ version(LLVMDC)
+ {
+ return llvm_tanh(x);
+ }
+ else
+ {
+ return tango.stdc.math.tanhl(x);
+ }
}
debug(UnitTest) {
@@ -949,8 +1079,12 @@
*/
float sqrt(float x) /* intrinsic */
{
- version(D_InlineAsm_X86)
+ version(LLVMDC)
{
+ return llvm_sqrt_f32(x);
+ }
+ else version(D_InlineAsm_X86)
+ {
asm
{
fld x;
@@ -965,8 +1099,12 @@
double sqrt(double x) /* intrinsic */ /// ditto
{
- version(D_InlineAsm_X86)
+ version(LLVMDC)
{
+ return llvm_sqrt_f64(x);
+ }
+ else version(D_InlineAsm_X86)
+ {
asm
{
fld x;
@@ -981,8 +1119,12 @@
real sqrt(real x) /* intrinsic */ /// ditto
{
- version(D_InlineAsm_X86)
+ version(LLVMDC)
{
+ return llvm_sqrt_f80(x);
+ }
+ else version(D_InlineAsm_X86)
+ {
asm
{
fld x;
@@ -1045,7 +1187,14 @@
*/
real cbrt(real x)
{
- return tango.stdc.math.cbrtl(x);
+ version(LLVMDC)
+ {
+ return llvm_cbrt(x);
+ }
+ else
+ {
+ return tango.stdc.math.cbrtl(x);
+ }
}
@@ -1067,7 +1216,14 @@
*/
real exp(real x)
{
- return tango.stdc.math.expl(x);
+ version(LLVMDC)
+ {
+ return llvm_exp(x);
+ }
+ else
+ {
+ return tango.stdc.math.expl(x);
+ }
}
debug(UnitTest) {
@@ -1093,7 +1249,14 @@
*/
real expm1(real x)
{
- return tango.stdc.math.expm1l(x);
+ version(LLVMDC)
+ {
+ return llvm_expm1(x);
+ }
+ else
+ {
+ return tango.stdc.math.expm1l(x);
+ }
}
debug(UnitTest) {
@@ -1115,7 +1278,14 @@
*/
real exp2(real x)
{
- return tango.stdc.math.exp2l(x);
+ version(LLVMDC)
+ {
+ return llvm_exp2(x);
+ }
+ else
+ {
+ return tango.stdc.math.exp2l(x);
+ }
}
debug(UnitTest) {
@@ -1141,7 +1311,14 @@
*/
real log(real x)
{
- return tango.stdc.math.logl(x);
+ version(LLVMDC)
+ {
+ return llvm_log(x);
+ }
+ else
+ {
+ return tango.stdc.math.logl(x);
+ }
}
debug(UnitTest) {
@@ -1167,7 +1344,14 @@
*/
real log1p(real x)
{
- return tango.stdc.math.log1pl(x);
+ version(LLVMDC)
+ {
+ return llvm_log1p(x);
+ }
+ else
+ {
+ return tango.stdc.math.log1pl(x);
+ }
}
debug(UnitTest) {
@@ -1190,7 +1374,14 @@
*/
real log2(real x)
{
- return tango.stdc.math.log2l(x);
+ version(LLVMDC)
+ {
+ return llvm_log2(x);
+ }
+ else
+ {
+ return tango.stdc.math.log2l(x);
+ }
}
debug(UnitTest) {
@@ -1212,7 +1403,14 @@
*/
real log10(real x)
{
- return tango.stdc.math.log10l(x);
+ version(LLVMDC)
+ {
+ return llvm_log10(x);
+ }
+ else
+ {
+ return tango.stdc.math.log10l(x);
+ }
}
debug(UnitTest) {
@@ -1477,7 +1675,14 @@
}
}
}
- return tango.stdc.math.powl(x, y);
+ version(LLVMDC)
+ {
+ return llvm_pow(x, y);
+ }
+ else
+ {
+ return tango.stdc.math.powl(x, y);
+ }
}
debug(UnitTest) {
@@ -1823,6 +2028,10 @@
}
return n;
}
+ else version(LLVMDC)
+ {
+ return llvm_lrint(x);
+ }
else
{
return tango.stdc.math.lrintl(x);
@@ -1842,6 +2051,10 @@
}
return n;
}
+ else version(LLVMDC)
+ {
+ return llvm_llrint(x);
+ }
else
{
return tango.stdc.math.llrintl(x);
Index: tango/stdc/stdlib.d
===================================================================
--- tango/stdc/stdlib.d (revision 3819)
+++ tango/stdc/stdlib.d (working copy)
@@ -94,6 +94,11 @@
{
void* alloca(size_t size);
}
+else version( LLVMDC )
+{
+ pragma(alloca)
+ void* alloca(size_t size);
+}
else version( GNU )
{
private import gcc.builtins;
Index: tango/stdc/stdarg.d
===================================================================
--- tango/stdc/stdarg.d (revision 3819)
+++ tango/stdc/stdarg.d (working copy)
@@ -13,6 +13,10 @@
{
public import std.c.stdarg;
}
+else version( LLVMDC )
+{
+ public import llvmdc.cstdarg;
+}
else
{
alias void* va_list;

4
runtime/patch-tango.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash
cd ../tango
patch -p0 < ../runtime/llvmdc.diff