Hi, during the last few days I tried to get D running on s390x (apparently the first Big Endian platform to try it?). I did not yet go through the code systematically and add a version(SystemZ) in every place where it might be needed but rather tried to fix test failures as they arose.
After enabling the architecture in the configure files and adding TLS support (see initial.diff) the test suite showed 200 something failures. Including big endian handling in some test cases (tests.diff), the number of failures went down to ~130. Some more involved cases are left: dmd/constfold.c handles 'a' ~ "abc" but fails because 'a' is treated as int64 and only the first bytes are memcpy'd into the result buffer. When using a similar logic as used for "abc" ~ a. This works but seems a rather hacky approach (cat.diff). An even more hacky fix I applied for libdruntime/rt/aaA.d (align.diff) where algn = 0 is passed to the talign function. I suppose it shouldn't ever be called with algn = 0 but the alignment should be set somewhere else initially? Another problem is printing of characters. std.uni.isGraphical returns false for standard ASCII characters because of the trie traversal or rather the final lookup in memory via PackedPtr cast(inout(T))(cast(U*) origin)[idx] This gets the first byte but should get the last byte on Big Endian. A simple + ubyte[] buf = nativeToLittleEndian (origin[idx]); + auto val = cast(inout(T))(buf.peek!U()); helps here, but has two problems: - peek!U() apparently does not work in CTFE and subsequently all compile-time unit tests fail. - simpleIndex() is called in other places and also does the wrong thing return cast(T)((origin[q] >> bits*r) & mask) Refraining from peek!... I tried working around it by extracting bytes and reversing the order but this seems to hacky to create a diff :) I got it to work for test28.d:test39() but the unit tests still fail. Is there a way to debug the compile-time unit tests easily? What's the preferred method to do "the right thing" even at compile time? Any other things that should be looked at? Any comments to the diffs so far? Regards Robin
diff --git a/libphobos/libdruntime/rt/aaA.d b/libphobos/libdruntime/rt/aaA.d index 631847e4c2b..92f2c70f569 100644 --- a/libphobos/libdruntime/rt/aaA.d +++ b/libphobos/libdruntime/rt/aaA.d @@ -291,6 +291,8 @@ TypeInfo_Struct fakeEntryTI(const TypeInfo keyti, const TypeInfo valti) private size_t talign(size_t tsize, size_t algn) @safe pure nothrow @nogc { + if (algn == 0) + return tsize; immutable mask = algn - 1; assert(!(mask & algn)); return (tsize + mask) & ~mask;
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c index ddd356bb966..4138563d599 100644 --- a/gcc/d/dmd/constfold.c +++ b/gcc/d/dmd/constfold.c @@ -1752,14 +1752,17 @@ UnionExp Cat(Type *type, Expression *e1, Expression *e2) } else if (e1->op == TOKint64 && e2->op == TOKstring) { - // Concatenate the strings + // [w|d]?char ~ string --> string + // We assume that we only ever prepend one char of the same type + // (wchar,dchar) as the string's characters. + StringExp *es2 = (StringExp *)e2; size_t len = 1 + es2->len; unsigned char sz = es2->sz; dinteger_t v = e1->toInteger(); void *s = mem.xmalloc((len + 1) * sz); - memcpy((char *)s, &v, sz); + Port::valcpy((char *)s, v, sz); memcpy((char *)s + sz, es2->string, es2->len * sz); // Add terminating 0
diff --git a/libphobos/configure.tgt b/libphobos/configure.tgt index 0471bfd816b..4ea91c949d7 100644 --- a/libphobos/configure.tgt +++ b/libphobos/configure.tgt @@ -32,6 +32,8 @@ case "${target}" in ;; x86_64-*-netbsd* | i?86-*-netbsd*) ;; + s390*-linux*) + ;; *) UNSUPPORTED=1 ;; diff --git a/libphobos/libdruntime/rt/sections_elf_shared.d b/libphobos/libdruntime/rt/sections_elf_shared.d index d4e1ff07699..85e2b768a87 100644 --- a/libphobos/libdruntime/rt/sections_elf_shared.d +++ b/libphobos/libdruntime/rt/sections_elf_shared.d @@ -978,7 +978,10 @@ struct tls_index } } +import gcc.builtins; + extern(C) void* __tls_get_addr(tls_index* ti) nothrow @nogc; +extern(C) void* __tls_get_addr_internal(tls_index* ti) nothrow @nogc; /* The dynamic thread vector (DTV) pointers may point 0x8000 past the start of * each TLS block. This is at least true for PowerPC and Mips platforms. @@ -1012,6 +1015,8 @@ else version (MIPS32) enum TLS_DTV_OFFSET = 0x8000; else version (MIPS64) enum TLS_DTV_OFFSET = 0x8000; +else version (SystemZ) + enum TLS_DTV_OFFSET = 0x0; else static assert( false, "Platform not supported." ); @@ -1022,5 +1027,13 @@ void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc // base offset auto ti = tls_index(mod, 0); - return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz]; + + version (SystemZ) + { + auto idx = cast(void *)__tls_get_addr_internal(&ti) + + cast(ulong)__builtin_thread_pointer (); + return idx[0 .. sz]; + } + else + return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz]; }
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d index 812b36649aa..a46bf53fb13 100644 --- a/gcc/testsuite/gdc.dg/simd.d +++ b/gcc/testsuite/gdc.dg/simd.d @@ -1576,7 +1576,10 @@ ubyte[16] foounsto() void testOPvecunsto() { auto a = foounsto(); - assert(a == [0, 0, 64, 65, 0, 0, 64, 65, 0, 0, 64, 65, 0, 0, 64, 65]); + version(littleEndian) + assert(a == [0, 0, 64, 65, 0, 0, 64, 65, 0, 0, 64, 65, 0, 0, 64, 65]); + version(bigEndian) + assert(a == [65, 64, 0, 0, 65, 64, 0, 0, 65, 64, 0, 0, 65, 64, 0, 0]); } /*****************************************/ diff --git a/gcc/testsuite/gdc.test/runnable/mars1.d b/gcc/testsuite/gdc.test/runnable/mars1.d index 1f4e55d9ac4..91d93dbf81e 100644 --- a/gcc/testsuite/gdc.test/runnable/mars1.d +++ b/gcc/testsuite/gdc.test/runnable/mars1.d @@ -238,13 +238,13 @@ void test13023(ulong n) struct U { int a; union { char c; int d; } long b; } -U f = { b:3, d:2, a:1 }; +U f = { b:3, d:0x22222222, a:1 }; void testU() { assert(f.b == 3); - assert(f.d == 2); - assert(f.c == 2); + assert(f.d == 0x22222222); + assert(f.c == 0x22); assert(f.a == 1); assert(f.sizeof == 16); assert(U.sizeof == 16); diff --git a/gcc/testsuite/gdc.test/runnable/test12.d b/gcc/testsuite/gdc.test/runnable/test12.d index 7656de70af6..f38c94dcd23 100644 --- a/gcc/testsuite/gdc.test/runnable/test12.d +++ b/gcc/testsuite/gdc.test/runnable/test12.d @@ -624,7 +624,10 @@ int hoge(S29 s) { char[10] b; printf("%x\n", s); sprintf(b.ptr, "%x", s); +version(littleEndian) assert(b[0 .. 7] == "4030201"); +version(bigEndian) + assert(b[0 .. 7] == "1020304"); return 0; } diff --git a/gcc/testsuite/gdc.test/runnable/test23.d b/gcc/testsuite/gdc.test/runnable/test23.d index ee17be0b00f..120ee3d380c 100644 --- a/gcc/testsuite/gdc.test/runnable/test23.d +++ b/gcc/testsuite/gdc.test/runnable/test23.d @@ -565,7 +565,10 @@ void test25() auto str3 = cast(wchar[3])("defghi"); writefln("str3: ", (cast(char[])str3).length , " : ", (cast(char[])str3)); - assert(cast(char[])str3 == "d\000e\000f\000"c); + version(littleEndian) + assert(cast(char[])str3 == "d\000e\000f\000"c); + version(bigEndian) + assert(cast(char[])str3 == "\000d\000e\000f"c); } /*******************************************/ diff --git a/gcc/testsuite/gdc.test/runnable/test4.d b/gcc/testsuite/gdc.test/runnable/test4.d index f008da6da72..ff6f6d407ed 100644 --- a/gcc/testsuite/gdc.test/runnable/test4.d +++ b/gcc/testsuite/gdc.test/runnable/test4.d @@ -254,6 +254,16 @@ else version(ARM) assert(TRECT6.BottomRight.offsetof == 16); assert(TRECT6.foo2.offsetof == 24); } +else version(SystemZ) +{ + assert(TRECT6.Left.offsetof == 8); + assert(TRECT6.Top.offsetof == 12); + assert(TRECT6.Right.offsetof == 16); + assert(TRECT6.Bottom.offsetof == 20); + assert(TRECT6.TopLeft.offsetof == 8); + assert(TRECT6.BottomRight.offsetof == 16); + assert(TRECT6.foo2.offsetof == 24); +} else { assert(TRECT6.Left.offsetof == 4);