[RFC] D support for S/390

Message ID 4514fe28-8acb-f0fd-510b-6568fda8bf4c@linux.ibm.com
State New
Headers show
Series
  • [RFC] D support for S/390
Related show

Commit Message

Robin Dapp March 15, 2019, 3:49 p.m.
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

Comments

Iain Buclaw March 18, 2019, 9:59 a.m. | #1
On Fri, 15 Mar 2019 at 16:50, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> 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.

>


HPPA has been somewhat ported, which is BigEndian as well.  But I've
not done any testing beyond just the druntime unittests.

I still have an image available locally and a little more free time
now, so can kickstart a rebuild and start looking at the other
testsuite parts, as the same endian problems should show themselves up
there as well.

>

> After enabling the architecture in the configure files and adding TLS

> support (see initial.diff) the test suite showed 200 something failures.

>


Thanks, I was unsure what to do with the s390 port regarding TLS.

> Including big endian handling in some test cases (tests.diff), the

> number of failures went down to ~130.

>


The changes so far look reasonable, although the version conditions
are LittleEndian and BigEndian.

> 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).

>


Port::valcpy was introduced precisely for the lack of endian-neutral
code in the dmd front-end, so it looks reasonable to me.  I'll send it
upstream if you have no objection to that.

> 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?

>


Alignment is written to TypeInfo, I don't think it should ever be
zero.  That would mean that it isn't being generated by the compiler,
or read by the library correctly, so something else is amiss.

> 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?

>


There's pragma(msg) that can be used in user code.

i.e:
    int foo() { return 42; }
    enum A = foo();
    pragma(msg, A);  // Prints '42' at compile-time.

Otherwise, it's just stepping through CTFE in the compiler front-end
(dmd/dinterpret.c, entrypoint is interpret), and using e->toChars() /
s->toChars() to get the string representation of intermediate
expressions/values.

--
Iain
Segher Boessenkool March 18, 2019, 8:09 p.m. | #2
Hi!

On Mon, Mar 18, 2019 at 10:59:26AM +0100, Iain Buclaw wrote:
> On Fri, 15 Mar 2019 at 16:50, Robin Dapp <rdapp@linux.ibm.com> wrote:

> > 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.

> >

> 

> HPPA has been somewhat ported, which is BigEndian as well.  But I've

> not done any testing beyond just the druntime unittests.


powerpc64-linux works as well, no failures in the gdc testsuite at all,
both -m64 and -m32.  No phobos yet though.


Segher
Robin Dapp March 19, 2019, 12:07 p.m. | #3
Hi,

> Alignment is written to TypeInfo, I don't think it should ever be

> zero.  That would mean that it isn't being generated by the compiler,

> or read by the library correctly, so something else is amiss.


it took me a while to see that in libphobos/libdruntime/object.d

 override @property size_t talign() nothrow pure const {return m_align;}

returns a size_t but m_align is a uint.  The type info seems to be
stored in memory by the compiler and writes a GCC "sizetype".  When
using it, we only emit a 4-byte read which loads the first half of the
stored 8 bytes.  This will work on a little-endian machine but fail on
big endian.

I'd hope it is safe to change m_align's type to size_t since, as far as
I can tell, the compiler will always write 8 bytes and the memory layout
will not be changed by that.

Does this [1] look reasonable?

Regards
 Robin

---

[1]
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..1bd94c33e82 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -954,7 +954,7 @@ public:
        StructFlags m_flags;
        void function(void*) xdtor;
        void function(void*) xpostblit;
-       uint m_align;
+       size_t m_align;
        version (X86_64)
            TypeInfo m_arg1;
            TypeInfo m_arg2;
@@ -1032,7 +1032,7 @@ public:
     else
       this->layout_field (null_pointer_node);

-    /* uint m_align;  */
+    /* size_t m_align;  */
     this->layout_field (size_int (ti->alignsize ()));

     if (global.params.is64bit)
diff --git a/libphobos/libdruntime/object.d b/libphobos/libdruntime/object.d
index 38bd0ae1f6b..bb821bf7040 100644
--- a/libphobos/libdruntime/object.d
+++ b/libphobos/libdruntime/object.d
@@ -1226,7 +1226,7 @@ class TypeInfo_Struct : TypeInfo
     }
     void function(void*)                    xpostblit;

-    uint m_align;
+    size_t m_align;

     override @property immutable(void)* rtInfo() const { return m_RTInfo; }
Richard Biener March 19, 2019, 12:49 p.m. | #4
On March 19, 2019 1:07:26 PM GMT+01:00, Robin Dapp <rdapp@linux.ibm.com> wrote:
>Hi,

>

>> Alignment is written to TypeInfo, I don't think it should ever be

>> zero.  That would mean that it isn't being generated by the compiler,

>> or read by the library correctly, so something else is amiss.

>

>it took me a while to see that in libphobos/libdruntime/object.d

>

>override @property size_t talign() nothrow pure const {return m_align;}

>

>returns a size_t but m_align is a uint.  The type info seems to be

>stored in memory by the compiler and writes a GCC "sizetype".  


It should probably use sth specified by the C ABI instead, like using size_type_node which maps to the targets size_t rather than the internal sizetype.

When
>using it, we only emit a 4-byte read which loads the first half of the

>stored 8 bytes.  This will work on a little-endian machine but fail on

>big endian.

>

>I'd hope it is safe to change m_align's type to size_t since, as far as

>I can tell, the compiler will always write 8 bytes and the memory

>layout

>will not be changed by that.

>

>Does this [1] look reasonable?

>

>Regards

> Robin

>

>---

>

>[1]

>diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc

>index dac66acdcd4..1bd94c33e82 100644

>--- a/gcc/d/typeinfo.cc

>+++ b/gcc/d/typeinfo.cc

>@@ -954,7 +954,7 @@ public:

>        StructFlags m_flags;

>        void function(void*) xdtor;

>        void function(void*) xpostblit;

>-       uint m_align;

>+       size_t m_align;

>        version (X86_64)

>            TypeInfo m_arg1;

>            TypeInfo m_arg2;

>@@ -1032,7 +1032,7 @@ public:

>     else

>       this->layout_field (null_pointer_node);

>

>-    /* uint m_align;  */

>+    /* size_t m_align;  */

>     this->layout_field (size_int (ti->alignsize ()));

>

>     if (global.params.is64bit)

>diff --git a/libphobos/libdruntime/object.d

>b/libphobos/libdruntime/object.d

>index 38bd0ae1f6b..bb821bf7040 100644

>--- a/libphobos/libdruntime/object.d

>+++ b/libphobos/libdruntime/object.d

>@@ -1226,7 +1226,7 @@ class TypeInfo_Struct : TypeInfo

>     }

>     void function(void*)                    xpostblit;

>

>-    uint m_align;

>+    size_t m_align;

>

>override @property immutable(void)* rtInfo() const { return m_RTInfo; }
Iain Buclaw March 19, 2019, 1 p.m. | #5
On Tue, 19 Mar 2019 at 13:07, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> Hi,

>

> > Alignment is written to TypeInfo, I don't think it should ever be

> > zero.  That would mean that it isn't being generated by the compiler,

> > or read by the library correctly, so something else is amiss.

>

> it took me a while to see that in libphobos/libdruntime/object.d

>

>  override @property size_t talign() nothrow pure const {return m_align;}

>

> returns a size_t but m_align is a uint.  The type info seems to be

> stored in memory by the compiler and writes a GCC "sizetype".  When

> using it, we only emit a 4-byte read which loads the first half of the

> stored 8 bytes.  This will work on a little-endian machine but fail on

> big endian.

>

> I'd hope it is safe to change m_align's type to size_t since, as far as

> I can tell, the compiler will always write 8 bytes and the memory layout

> will not be changed by that.

>


So, when the initializer value type is larger than the field, it
truncates rather than rounds?

This would mean that StructFlags and ClassFlags will also both have a
wrong value as well.

> Does this [1] look reasonable?

>


If there's a compiler/library discrepancy, the compiler should be
adjusted to write out the value at the correct size.

I think the following below should do it.

-- 
Iain

--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
        flags |= ClassFlags::noPointers;

     Lhaspointers:
-       this->layout_field (size_int (flags));
+       this->layout_field (build_integer_cst (flags, d_uint_type));

        /* void *deallocator;  */
        tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
        if (cd->isCOMinterface ())
          flags |= ClassFlags::isCOMclass;

-       this->layout_field (size_int (flags));
+       this->layout_field (build_integer_cst (flags, d_uint_type));

        /* void *deallocator;
           OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));

     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);

     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));

     if (global.params.is64bit)
       {
@@ -1488,9 +1488,8 @@ create_typeinfo (Type *type, Module *mod)
              make_internal_typeinfo (tk, ident,
                                      array_type_node, array_type_node,
                                      ptr_type_node, ptr_type_node,
-                                     ptr_type_node, ptr_type_node,
-                                     size_type_node, ptr_type_node,
-                                     ptr_type_node, size_type_node,
+                                     ptr_type_node, ptr_type_node, d_uint_type,
+                                     ptr_type_node, ptr_type_node, d_uint_type,
                                      ptr_type_node, argtype, argtype, NULL);
            }
          t->vtinfo = TypeInfoStructDeclaration::create (t);
Robin Dapp March 19, 2019, 3:15 p.m. | #6
> This would mean that StructFlags and ClassFlags will also both have a

> wrong value as well.


Yes, can confirm that m_flags = 0 (instead of 1) for a struct containing
a pointer.

> If there's a compiler/library discrepancy, the compiler should be

> adjusted to write out the value at the correct size.

> 

> I think the following below should do it.


The diff fixes the problems for me.  I first encountered the algn = 0 in
an associative array and couldn't immediately link it to structs.  In
order to make pinpointing easier in the future I wrote a simple test
case for this that I'm going to post with the next diff.

Regards
 Robin
Robin Dapp March 20, 2019, 9:57 a.m. | #7
Hi,

the unicode tables in std.internal.unicode_tables are apparently auto
generated and loaded at (libphobos) compile time.  They are also in
little endian format.  Is the tool to generate them available somewhere?
 I wanted to start converting them to little endian before loading but
this will prove difficult at compile time again :)

Regards
 Robin
Iain Buclaw March 20, 2019, 11:27 a.m. | #8
On Wed, 20 Mar 2019 at 10:57, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> Hi,

>

> the unicode tables in std.internal.unicode_tables are apparently auto

> generated and loaded at (libphobos) compile time.  They are also in

> little endian format.  Is the tool to generate them available somewhere?

>  I wanted to start converting them to little endian before loading but

> this will prove difficult at compile time again :)

>


Hi,

I will ask if the author still has the utility available.

My guess would be that the data used for input would have been
retrieved from here.

http://www.unicode.org/Public/4.1.0/ucd/

Will let you know as soon as I find out more.

-- 
Iain
Iain Buclaw March 20, 2019, 6:26 p.m. | #9
On Wed, 20 Mar 2019 at 12:27, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>

> On Wed, 20 Mar 2019 at 10:57, Robin Dapp <rdapp@linux.ibm.com> wrote:

> >

> > Hi,

> >

> > the unicode tables in std.internal.unicode_tables are apparently auto

> > generated and loaded at (libphobos) compile time.  They are also in

> > little endian format.  Is the tool to generate them available somewhere?

> >  I wanted to start converting them to little endian before loading but

> > this will prove difficult at compile time again :)

> >

>

> Hi,

>

> I will ask if the author still has the utility available.

>

> My guess would be that the data used for input would have been

> retrieved from here.

>

> http://www.unicode.org/Public/4.1.0/ucd/

>

> Will let you know as soon as I find out more.

>


It comes from this repo: https://github.com/DmitryOlshansky/gsoc-bench-2012

I've tested build them using the following:

    mkdir build; cd build
    sh ../get-uni.sh
    gdc -m64 -frelease ../gen_uni.d randAA.d -o gen_uni_64 &
    gdc -m32 -frelease ../gen_uni.d randAA.d -o gen_uni_64 &
    wait
    mkdir 64
    ./gen_uni_64
    mv unicode_*.d 64
    mkdir 32
    ./gen_uni_32
    mv unicode_*.d 32
    for name in 64/*.d ; do
        name32=`echo $name | sed 's/64/32/'`
        sed -n '/^static if(size_t.sizeof == 4) {$/,$p' $name32 >> $name
    done
    mv 64/*.d .
    rm -rf 64/ 32/

Then a final clean-up using dfmt
(https://github.com/dlang-community/dfmt - build with: make gdc)

    dfmt --inplace --max_line_length=80 unicode_*.d

However... it looks like upstream phobos has done some extra tweaks
and formatting since the original check-in of the sources, so any new
regeneration would have to re-add those ad-hoc changes back in...

Are the values inside the tables the problem? Or just some of the
helper functions/templates that interact with them to generate the
static data?

If the latter, then a rebuild of the files may not be necessary.

Regards
-- 
Iain
Rainer Orth March 20, 2019, 8:35 p.m. | #10
Iain Buclaw <ibuclaw@gdcproject.org> writes:

> On Fri, 15 Mar 2019 at 16:50, Robin Dapp <rdapp@linux.ibm.com> wrote:

>>

>> 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.

>

> HPPA has been somewhat ported, which is BigEndian as well.  But I've

> not done any testing beyond just the druntime unittests.


there's also SPARC, but unlike S/390 and HP-PA it's a strict alignment
target, so all execution tests fail due to PR d/88462...

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Robin Dapp March 22, 2019, 3:34 p.m. | #11
Hi,

> Are the values inside the tables the problem? Or just some of the

> helper functions/templates that interact with them to generate the

> static data?

> 

> If the latter, then a rebuild of the files may not be necessary.


I managed to get this to work without rebuilding the files.  After
checking more carefully, it turned out that simpleIndex already does the
right thing and only a few simple changes were necessary.

Continuing with the phobos test suite failures I managed to fix some
more problems.  I'm down to 32 failures now with the attached patch
(single file this time).  It doesn't even seem that much now, debugging
the failures took me longer than what the diff reflects :)

An imho nasty (since unexpected) one was the implicit pointer cast from
size_t* to int* during a foreach delegate (see aApply.d:_aApplycd2).  I
did not check where exactly the cast happens but changing the int inside
the foreach header to size_t fixed it.

I also found some wrong POSIX defines and did not check all the others.
 A more thorough check might be necessary in the future.

The tests I did not yet check/fix are shared libphobos, math and
numeric-related as well as some regex and curl tests.

Any chance we will get some or most of the diff in before GCC 9?
(provided they do not break anything else of course)  I'm going to be
away for two weeks and will continue with the remaining failures afterwards.

Regards
 Robin
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/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..21bc4d62a68 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
 	flags |= ClassFlags::noPointers;
 
     Lhaspointers:
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;  */
 	tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
 	if (cd->isCOMinterface ())
 	  flags |= ClassFlags::isCOMclass;
 
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags));
 
 	/* void *deallocator;
 	   OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);
 
     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
 
     if (global.params.is64bit)
       {
@@ -1489,8 +1489,8 @@ create_typeinfo (Type *type, Module *mod)
 				      array_type_node, array_type_node,
 				      ptr_type_node, ptr_type_node,
 				      ptr_type_node, ptr_type_node,
-				      size_type_node, ptr_type_node,
-				      ptr_type_node, size_type_node,
+				      d_uint_type, ptr_type_node,
+				      ptr_type_node, d_uint_type,
 				      ptr_type_node, argtype, argtype, NULL);
 	    }
 	  t->vtinfo = TypeInfoStructDeclaration::create (t);
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index e36a2585027..079e149826a 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -895,7 +895,7 @@ void check186(in S186 obj, byte fieldB)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == 0x0200000000000002);
     assert(fieldB == 0);
 }
 
@@ -907,7 +907,7 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == 0x0200000000000002);
 
     obj = S186(val);
     check186(obj, obj.fieldB);
@@ -915,12 +915,12 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == 0x0200000000000002);
 }
 
 void test186()
 {
-    test186a(2);
+    test186a(0x0200000000000002);
 }
 
 /******************************************/
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d
index 812b36649aa..5715dd5bced 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..338afc191ee 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);
-    assert(b[0 .. 7] == "4030201");
+    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..eac2b20b7dd 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);
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/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 817790ab7eb..4665f3abcb0 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -120,6 +120,13 @@ version (CRuntime_Glibc)
     enum F_SETLK        = 6;
     enum F_SETLKW       = 7;
   }
+  else version (SystemZ)
+  {
+    static assert(off_t.sizeof == 8);
+    enum F_GETLK        = 5;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
   else
   static if ( __USE_FILE_OFFSET64 )
   {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 8c78ba677a4..fbd556a4ac8 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -741,12 +741,12 @@ version (CRuntime_Glibc)
             alias __ino_t = c_ulong;
             alias __ino64_t = ulong;
             alias __mode_t = uint;
-            alias __nlink_t = uint;
+            alias __nlink_t = ulong;
             alias __uid_t = uint;
             alias __gid_t = uint;
             alias __off_t = c_long;
             alias __off64_t = long;
-            alias __blksize_t = int;
+            alias __blksize_t = c_long;
             alias __blkcnt_t = c_long;
             alias __blkcnt64_t = long;
             alias __timespec = timespec;
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/libphobos/src/std/outbuffer.d b/libphobos/src/std/outbuffer.d
index 1d594982cc1..6f42ab26f99 100644
--- a/libphobos/src/std/outbuffer.d
+++ b/libphobos/src/std/outbuffer.d
@@ -408,11 +408,17 @@ class OutBuffer
   {
     OutBuffer buf = new OutBuffer();
     "hello"w.copy(buf);
-    assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(LittleEndian)
+	assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(BigEndian)
+	assert(buf.toBytes() == "\x00h\x00e\x00l\x00l\x00o");
   }
   {
     OutBuffer buf = new OutBuffer();
     "hello"d.copy(buf);
-    assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(LittleEndian)
+	assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(BigEndian)
+	assert(buf.toBytes() == "\x00\x00\x00h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o");
   }
 }
diff --git a/libphobos/src/std/uni.d b/libphobos/src/std/uni.d
index 5f24ad16be5..45bf1233129 100644
--- a/libphobos/src/std/uni.d
+++ b/libphobos/src/std/uni.d
@@ -770,6 +770,8 @@ version (X86)
     enum hasUnalignedReads = true;
 else version (X86_64)
     enum hasUnalignedReads = true;
+else version (SystemZ)
+    enum hasUnalignedReads = true;
 else
     enum hasUnalignedReads = false; // better be safe then sorry
 
@@ -1208,9 +1210,9 @@ pure nothrow:
 
     private T simpleIndex(size_t n) inout
     {
-        immutable q = n / factor;
-        immutable r = n % factor;
-        return cast(T)((origin[q] >> bits*r) & mask);
+	immutable q = n / factor;
+	immutable r = n % factor;
+	return cast(T)((origin[q] >> bits*r) & mask);
     }
 
     private void simpleWrite(TypeOfBitPacked!T val, size_t n)
@@ -1245,8 +1247,13 @@ pure nothrow:
 
         T opIndex(size_t idx) inout
         {
-            return __ctfe ? simpleIndex(idx) :
-                cast(inout(T))(cast(U*) origin)[idx];
+	    T ret;
+	    version (LittleEndian)
+		ret = __ctfe ? simpleIndex(idx) :
+		    cast(inout(T))(cast(U*) origin)[idx];
+	    else
+		ret = simpleIndex (idx);
+	    return ret;
         }
 
         static if (isBitPacked!T) // lack of user-defined implicit conversion
@@ -1259,10 +1266,15 @@ pure nothrow:
 
         void opIndexAssign(TypeOfBitPacked!T val, size_t idx)
         {
-            if (__ctfe)
-                simpleWrite(val, idx);
-            else
-                (cast(U*) origin)[idx] = cast(U) val;
+	  version (LittleEndian)
+	    {
+	      if (__ctfe)
+		simpleWrite(val, idx);
+	      else
+		(cast(U*) origin)[idx] = cast(U) val;
+	    }
+	  else
+	      simpleWrite(val, idx);
         }
     }
     else
diff --git a/libphobos/src/std/xml.d b/libphobos/src/std/xml.d
index 770c56fdbfb..78c5d563abc 100644
--- a/libphobos/src/std/xml.d
+++ b/libphobos/src/std/xml.d
@@ -2201,8 +2201,8 @@ private
         mixin Check!("Chars");
 
         dchar c;
-        int n = -1;
-        foreach (int i,dchar d; s)
+        long n = -1;
+        foreach (size_t i,dchar d; s)
         {
             if (!isChar(d))
             {
@@ -2238,8 +2238,11 @@ private
         mixin Check!("Name");
 
         if (s.length == 0) fail();
-        int n;
-        foreach (int i,dchar c;s)
+        long n;
+	// i must not be smaller than size_t because size_t is used internally
+	// in aApply.d and it will be cast e.g. to (int *) which fails on
+	// big-endian machines.
+        foreach (size_t i,dchar c;s)
         {
             if (c == '_' || c == ':' || isLetter(c)) continue;
             if (i == 0) fail();
diff --git a/libphobos/testsuite/libphobos.typeinfo/struct-align.d b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
new file mode 100644
index 00000000000..384d95e247c
--- /dev/null
+++ b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
@@ -0,0 +1,13 @@
+module structalign;
+
+void main ()
+{
+  struct K { int *a; };
+  K k;
+  auto ti = typeid (k);
+
+  assert (ti.flags () == 1);
+
+  auto ti2 = typeid (k.a);
+  assert (ti.talign () == ti2.talign ());
+}
Rainer Orth April 3, 2019, 12:30 p.m. | #12
Hi Robin,

>> Are the values inside the tables the problem? Or just some of the

>> helper functions/templates that interact with them to generate the

>> static data?

>> 

>> If the latter, then a rebuild of the files may not be necessary.

>

> I managed to get this to work without rebuilding the files.  After

> checking more carefully, it turned out that simpleIndex already does the

> right thing and only a few simple changes were necessary.

>

> Continuing with the phobos test suite failures I managed to fix some

> more problems.  I'm down to 32 failures now with the attached patch

> (single file this time).  It doesn't even seem that much now, debugging

> the failures took me longer than what the diff reflects :)

>

> An imho nasty (since unexpected) one was the implicit pointer cast from

> size_t* to int* during a foreach delegate (see aApply.d:_aApplycd2).  I

> did not check where exactly the cast happens but changing the int inside

> the foreach header to size_t fixed it.

>

> I also found some wrong POSIX defines and did not check all the others.

>  A more thorough check might be necessary in the future.

>

> The tests I did not yet check/fix are shared libphobos, math and

> numeric-related as well as some regex and curl tests.

>

> Any chance we will get some or most of the diff in before GCC 9?

> (provided they do not break anything else of course)  I'm going to be

> away for two weeks and will continue with the remaining failures afterwards.


I've applied the non-S/390 parts of the patch to move further along on
Solaris/SPARC (both 32 and 64-bit) since SPARC is another big-endian
target.  I immediately ran into two issues with your patch:

/vol/gcc/src/hg/trunk/solaris/libphobos/src/std/xml.d:2216:19: error: cannot implicitly convert expression (n) of type long to uint
 2216 |             s = s[n..$];
      |                   ^
/vol/gcc/src/hg/trunk/solaris/libphobos/src/std/xml.d:2254:23: error: cannot implicitly convert expression (n) of type long to uint
 2254 |         name = s[0 .. n];
      |                       ^
/vol/gcc/src/hg/trunk/solaris/libphobos/src/std/xml.d:2255:15: error: cannot implicitly convert expression (n) of type long to uint
 2255 |         s = s[n..$];
      |               ^

This will occur on any 32-bit target.  The following patch (using
ssize_t instead) allowed the code to compile:
diff --git a/libphobos/src/std/xml.d b/libphobos/src/std/xml.d
--- a/libphobos/src/std/xml.d
+++ b/libphobos/src/std/xml.d
@@ -2192,6 +2192,8 @@ private
         catch (Err e) { fail(e); }
     }
 
+    import core.sys.posix.sys.types : ssize_t;
+
     void checkChars(ref string s) @safe pure // rule 2
     {
         // TO DO - Fix std.utf stride and decode functions, then use those
@@ -2201,7 +2203,7 @@ private
         mixin Check!("Chars");
 
         dchar c;
-        long n = -1;
+        ssize_t n = -1;
         foreach (size_t i,dchar d; s)
         {
             if (!isChar(d))
@@ -2238,7 +2240,7 @@ private
         mixin Check!("Name");
 
         if (s.length == 0) fail();
-        long n;
+        ssize_t n;
 	// i must not be smaller than size_t because size_t is used internally
 	// in aApply.d and it will be cast e.g. to (int *) which fails on
 	// big-endian machines.
Another issue on 32-bit targets is

FAIL: gdc.dg/runnable.d   -O0  (test for excess errors)
Excess errors:
/vol/gcc/src/hg/trunk/solaris/gcc/testsuite/gdc.dg/runnable.d:923:13: error: function runnable.test186a (uint val) is not callable using argument types (long)

Again, this will occur on any 32-bit target.

Besides, you're quite inconsistent with the use of tab vs. blank in your
patch.  The D code uses only blanks as a rule, for example.

I've still got tons of execution failures with that augmented patch, but
those seem down to just a few root causes.

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Robin Dapp April 11, 2019, 3:43 p.m. | #13
Hi Rainer,

> This will occur on any 32-bit target.  The following patch (using

> ssize_t instead) allowed the code to compile:


thanks, included your fix and attempted a more generic version of the
186 test.

I also continued debugging some fails further:

- Most of the MurmurHash fails are simply due to the wrong byte order
being asserted but I did not yet check whether multi-chunk hashes are
more complicated to get right - I suppose not, though.

- The regex searches are even documented to not work properly on
big-endian platforms. I still guess they could be fixed without too much
effort.

- Math unit tests fail due to lower precision than on other machines.
Maybe this is because I only tested using -O0.

@Iain: With the patch as it is - hoping no additional tab/space damage
:) - is there any chance of getting it upstream anytime soon?

Regards
 Robin
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c
index ddd356bb966..cb58d4b4f5b 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/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..21bc4d62a68 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
 	flags |= ClassFlags::noPointers;
 
     Lhaspointers:
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;  */
 	tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
 	if (cd->isCOMinterface ())
 	  flags |= ClassFlags::isCOMclass;
 
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags));
 
 	/* void *deallocator;
 	   OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);
 
     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
 
     if (global.params.is64bit)
       {
@@ -1489,8 +1489,8 @@ create_typeinfo (Type *type, Module *mod)
 				      array_type_node, array_type_node,
 				      ptr_type_node, ptr_type_node,
 				      ptr_type_node, ptr_type_node,
-				      size_type_node, ptr_type_node,
-				      ptr_type_node, size_type_node,
+				      d_uint_type, ptr_type_node,
+				      ptr_type_node, d_uint_type,
 				      ptr_type_node, argtype, argtype, NULL);
 	    }
 	  t->vtinfo = TypeInfoStructDeclaration::create (t);
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index e36a2585027..8d9a5868831 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -890,12 +890,17 @@ struct S186
     }
 }
 
+static if (size_t.sizeof == 8)
+     size_t checkval = 0x0200000000000002;
+static if (size_t.sizeof == 4)
+     size_t checkval = 0x02000002;
+
 void check186(in S186 obj, byte fieldB)
 {
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
     assert(fieldB == 0);
 }
 
@@ -907,7 +912,7 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 
     obj = S186(val);
     check186(obj, obj.fieldB);
@@ -915,12 +920,12 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 }
 
 void test186()
 {
-    test186a(2);
+    test186a(checkval);
 }
 
 /******************************************/
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d
index 812b36649aa..7d0aa0168c0 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..db9b45cea61 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);
-    assert(b[0 .. 7] == "4030201");
+    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..eac2b20b7dd 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);
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/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 817790ab7eb..4665f3abcb0 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -120,6 +120,13 @@ version (CRuntime_Glibc)
     enum F_SETLK        = 6;
     enum F_SETLKW       = 7;
   }
+  else version (SystemZ)
+  {
+    static assert(off_t.sizeof == 8);
+    enum F_GETLK        = 5;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
   else
   static if ( __USE_FILE_OFFSET64 )
   {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 8c78ba677a4..fbd556a4ac8 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -741,12 +741,12 @@ version (CRuntime_Glibc)
             alias __ino_t = c_ulong;
             alias __ino64_t = ulong;
             alias __mode_t = uint;
-            alias __nlink_t = uint;
+            alias __nlink_t = ulong;
             alias __uid_t = uint;
             alias __gid_t = uint;
             alias __off_t = c_long;
             alias __off64_t = long;
-            alias __blksize_t = int;
+            alias __blksize_t = c_long;
             alias __blkcnt_t = c_long;
             alias __blkcnt64_t = long;
             alias __timespec = timespec;
diff --git a/libphobos/libdruntime/rt/sections_elf_shared.d b/libphobos/libdruntime/rt/sections_elf_shared.d
index d4e1ff07699..5cc7a866fcb 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/libphobos/src/std/outbuffer.d b/libphobos/src/std/outbuffer.d
index 1d594982cc1..e9301181640 100644
--- a/libphobos/src/std/outbuffer.d
+++ b/libphobos/src/std/outbuffer.d
@@ -408,11 +408,17 @@ class OutBuffer
   {
     OutBuffer buf = new OutBuffer();
     "hello"w.copy(buf);
-    assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(LittleEndian)
+        assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(BigEndian)
+        assert(buf.toBytes() == "\x00h\x00e\x00l\x00l\x00o");
   }
   {
     OutBuffer buf = new OutBuffer();
     "hello"d.copy(buf);
-    assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(LittleEndian)
+        assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(BigEndian)
+        assert(buf.toBytes() == "\x00\x00\x00h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o");
   }
 }
diff --git a/libphobos/src/std/uni.d b/libphobos/src/std/uni.d
index 5f24ad16be5..baee073bfc2 100644
--- a/libphobos/src/std/uni.d
+++ b/libphobos/src/std/uni.d
@@ -770,6 +770,8 @@ version (X86)
     enum hasUnalignedReads = true;
 else version (X86_64)
     enum hasUnalignedReads = true;
+else version (SystemZ)
+    enum hasUnalignedReads = true;
 else
     enum hasUnalignedReads = false; // better be safe then sorry
 
@@ -1245,8 +1247,13 @@ pure nothrow:
 
         T opIndex(size_t idx) inout
         {
-            return __ctfe ? simpleIndex(idx) :
+            T ret;
+            version (LittleEndian)
+                ret = __ctfe ? simpleIndex(idx) :
                 cast(inout(T))(cast(U*) origin)[idx];
+            else
+                ret = simpleIndex (idx);
+            return ret;
         }
 
         static if (isBitPacked!T) // lack of user-defined implicit conversion
@@ -1259,10 +1266,15 @@ pure nothrow:
 
         void opIndexAssign(TypeOfBitPacked!T val, size_t idx)
         {
-            if (__ctfe)
-                simpleWrite(val, idx);
-            else
-                (cast(U*) origin)[idx] = cast(U) val;
+          version (LittleEndian)
+            {
+              if (__ctfe)
+                  simpleWrite(val, idx);
+              else
+                  (cast(U*) origin)[idx] = cast(U) val;
+            }
+          else
+              simpleWrite(val, idx);
         }
     }
     else
diff --git a/libphobos/src/std/xml.d b/libphobos/src/std/xml.d
index 770c56fdbfb..a0c5349d013 100644
--- a/libphobos/src/std/xml.d
+++ b/libphobos/src/std/xml.d
@@ -2192,6 +2192,8 @@ private
         catch (Err e) { fail(e); }
     }
 
+    import core.sys.posix.sys.types : ssize_t;
+
     void checkChars(ref string s) @safe pure // rule 2
     {
         // TO DO - Fix std.utf stride and decode functions, then use those
@@ -2201,8 +2203,8 @@ private
         mixin Check!("Chars");
 
         dchar c;
-        int n = -1;
-        foreach (int i,dchar d; s)
+        ssize_t n = -1;
+        foreach (size_t i,dchar d; s)
         {
             if (!isChar(d))
             {
@@ -2238,8 +2240,11 @@ private
         mixin Check!("Name");
 
         if (s.length == 0) fail();
-        int n;
-        foreach (int i,dchar c;s)
+        ssize_t n;
+        // i must not be smaller than size_t because size_t is used internally
+        // in aApply.d and it will be cast e.g. to (int *) which fails on
+        // big-endian machines.
+        foreach (size_t i,dchar c;s)
         {
             if (c == '_' || c == ':' || isLetter(c)) continue;
             if (i == 0) fail();
diff --git a/libphobos/testsuite/libphobos.typeinfo/struct-align.d b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
new file mode 100644
index 00000000000..72866517481
--- /dev/null
+++ b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
@@ -0,0 +1,13 @@
+module structalign;
+
+void main ()
+{
+    struct K { int *a; };
+    K k;
+    auto ti = typeid (k);
+
+    assert (ti.flags () == 1);
+
+    auto ti2 = typeid (k.a);
+    assert (ti.talign () == ti2.talign ());
+}
Iain Buclaw April 11, 2019, 3:57 p.m. | #14
On Thu, 11 Apr 2019 at 17:43, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> Hi Rainer,

>

> > This will occur on any 32-bit target.  The following patch (using

> > ssize_t instead) allowed the code to compile:

>

> thanks, included your fix and attempted a more generic version of the

> 186 test.

>

> I also continued debugging some fails further:

>

> - Most of the MurmurHash fails are simply due to the wrong byte order

> being asserted but I did not yet check whether multi-chunk hashes are

> more complicated to get right - I suppose not, though.

>

> - The regex searches are even documented to not work properly on

> big-endian platforms. I still guess they could be fixed without too much

> effort.

>

> - Math unit tests fail due to lower precision than on other machines.

> Maybe this is because I only tested using -O0.

>

> @Iain: With the patch as it is - hoping no additional tab/space damage

> :) - is there any chance of getting it upstream anytime soon?

>


I'll push for it tonight, thanks.

@Rainer Orth  any last requests before I commit the fix for PR
d/89255?  That will make testing individual library modules easier I
guess.

-- 
Iain
Rainer Orth April 11, 2019, 4 p.m. | #15
Hi Iain,

> @Rainer Orth  any last requests before I commit the fix for PR

> d/89255?  That will make testing individual library modules easier I

> guess.


no, the patch is perfectly fine as is.  Sorry for not following up
earlier; I've now tested it successfully on Solaris 11.[345]/x86 and am
also using it on Solaris 11.5/SPARC (still WIP, but getting closer).

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Rainer Orth April 11, 2019, 6:50 p.m. | #16
Hi Robin,

>> This will occur on any 32-bit target.  The following patch (using

>> ssize_t instead) allowed the code to compile:

>

> thanks, included your fix and attempted a more generic version of the

> 186 test.

>

> I also continued debugging some fails further:

>

> - Most of the MurmurHash fails are simply due to the wrong byte order

> being asserted but I did not yet check whether multi-chunk hashes are

> more complicated to get right - I suppose not, though.

>

> - The regex searches are even documented to not work properly on

> big-endian platforms. I still guess they could be fixed without too much

> effort.

>

> - Math unit tests fail due to lower precision than on other machines.

> Maybe this is because I only tested using -O0.


good.  I'm seeing those two, but at the moment concentrate on a couple
of Solaris/SPARC specific issues (mcontext_t was wrong, causing memory
corruption; need a different variant of makecontext; stack needs
doubleword alignment; some minor stuff).  64-bit results are not too bad ATM:

                === gdc Summary for unix/-m64 ===

# of expected passes            29159
# of unexpected failures        199
# of unsupported tests          20

                === libphobos Summary for unix/-m64 ===

# of expected passes            398
# of unexpected failures        22

and some of the failures also occur on Solaris/x86, but 32-bit execution
tests are terrible right now, mostly due to the same issue, I believe:

FAIL: libphobos.aa/test_aa.d execution test

Thread 2 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
0x0009c9b0 in rt.aaA.Impl.length() const (this=...)
    at /vol/gcc/src/hg/trunk/solaris/libphobos/libdruntime/rt/aaA.d:87
87	        assert(used >= deleted);
(gdb) where
#0  0x0009c9b0 in rt.aaA.Impl.length() const (this=...)
    at /vol/gcc/src/hg/trunk/solaris/libphobos/libdruntime/rt/aaA.d:87
#1  0x0009c960 in rt.aaA.AA.empty() const (this=...)
    at /vol/gcc/src/hg/trunk/solaris/libphobos/libdruntime/rt/aaA.d:44
#2  0x0009e83c in _aaValues (aa=..., keysz=4, valsz=1, 
    tiValueArray=0x718fc <initializer for TypeInfo_AS7test_aa15testKeysValues1FZ1T>) at /vol/gcc/src/hg/trunk/solaris/libphobos/libdruntime/rt/aaA.d:513
#3  0x00082688 in object.values!(test_aa.testKeysValues1().T[int], test_aa.testKeysValues1().T, int).values(test_aa.testKeysValues1().T[int]) (aa=...)
    at /vol/gcc/src/hg/trunk/solaris/libphobos/libdruntime/object.d:2171
#4  0x00077a9c in test_aa.testKeysValues1() ()
    at /vol/gcc/src/hg/trunk/solaris/libphobos/testsuite/libphobos.aa/test_aa.d:56
#5  0x00077604 in D main ()
    at /vol/gcc/src/hg/trunk/solaris/libphobos/testsuite/libphobos.aa/test_aa.d:3

1: x/i $pc
=> 0x9c9b0 <_D2rt3aaA4Impl6lengthMxFNaNbNdNiZk+32>:	ld  [ %g1 + 8 ], %g2
(gdb) p/x $g1
$1 = 0x8

Investigating this is my next task.

> @Iain: With the patch as it is - hoping no additional tab/space damage

> :) - is there any chance of getting it upstream anytime soon?


I noticed you missed one piece of Iain's typeinfo.cc patch, btw.:

diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -886,7 +886,7 @@ public:
 	if (cd->isCOMinterface ())
 	  flags |= ClassFlags::isCOMclass;
 
-	this->layout_field (build_integer_cst (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;
 	   OffsetTypeInfo[] m_offTi;  (not implemented)

	Rainer

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Robin Dapp April 18, 2019, 2:55 p.m. | #17
Hi Rainer,

> I noticed you missed one piece of Iain's typeinfo.cc patch, btw.:

> 

> diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc

> --- a/gcc/d/typeinfo.cc

> +++ b/gcc/d/typeinfo.cc

> @@ -886,7 +886,7 @@ public:

>  	if (cd->isCOMinterface ())

>  	  flags |= ClassFlags::isCOMclass;

>  

> -	this->layout_field (build_integer_cst (flags));

> +	this->layout_field (build_integer_cst (flags, d_uint_type));

>  

>  	/* void *deallocator;

>  	   OffsetTypeInfo[] m_offTi;  (not implemented)


thanks for catching this.  I amended the patch and ran the D test suite
on S/390 and i386 one more time.

For S/390 the number of FAILs is unchanged

                === libphobos Summary ===

# of expected passes            380
# of unexpected failures        30

Some of the FAILs are still a little worrying, like tests for "-shared"
which I haven't looked at at all so far.  Still, it's better than the
>200 before.


On i386 I see no FAILs with the patch.

Regards
 Robin
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c
index ddd356bb966..cb58d4b4f5b 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/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..865fde2c863 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
 	flags |= ClassFlags::noPointers;
 
     Lhaspointers:
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;  */
 	tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
 	if (cd->isCOMinterface ())
 	  flags |= ClassFlags::isCOMclass;
 
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;
 	   OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);
 
     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
 
     if (global.params.is64bit)
       {
@@ -1489,8 +1489,8 @@ create_typeinfo (Type *type, Module *mod)
 				      array_type_node, array_type_node,
 				      ptr_type_node, ptr_type_node,
 				      ptr_type_node, ptr_type_node,
-				      size_type_node, ptr_type_node,
-				      ptr_type_node, size_type_node,
+				      d_uint_type, ptr_type_node,
+				      ptr_type_node, d_uint_type,
 				      ptr_type_node, argtype, argtype, NULL);
 	    }
 	  t->vtinfo = TypeInfoStructDeclaration::create (t);
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index e36a2585027..8d9a5868831 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -890,12 +890,17 @@ struct S186
     }
 }
 
+static if (size_t.sizeof == 8)
+     size_t checkval = 0x0200000000000002;
+static if (size_t.sizeof == 4)
+     size_t checkval = 0x02000002;
+
 void check186(in S186 obj, byte fieldB)
 {
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
     assert(fieldB == 0);
 }
 
@@ -907,7 +912,7 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 
     obj = S186(val);
     check186(obj, obj.fieldB);
@@ -915,12 +920,12 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 }
 
 void test186()
 {
-    test186a(2);
+    test186a(checkval);
 }
 
 /******************************************/
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d
index 812b36649aa..7d0aa0168c0 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..db9b45cea61 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);
-    assert(b[0 .. 7] == "4030201");
+    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..eac2b20b7dd 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);
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/core/sys/posix/fcntl.d b/libphobos/libdruntime/core/sys/posix/fcntl.d
index 817790ab7eb..4665f3abcb0 100644
--- a/libphobos/libdruntime/core/sys/posix/fcntl.d
+++ b/libphobos/libdruntime/core/sys/posix/fcntl.d
@@ -120,6 +120,13 @@ version (CRuntime_Glibc)
     enum F_SETLK        = 6;
     enum F_SETLKW       = 7;
   }
+  else version (SystemZ)
+  {
+    static assert(off_t.sizeof == 8);
+    enum F_GETLK        = 5;
+    enum F_SETLK        = 6;
+    enum F_SETLKW       = 7;
+  }
   else
   static if ( __USE_FILE_OFFSET64 )
   {
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 8c78ba677a4..fbd556a4ac8 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -741,12 +741,12 @@ version (CRuntime_Glibc)
             alias __ino_t = c_ulong;
             alias __ino64_t = ulong;
             alias __mode_t = uint;
-            alias __nlink_t = uint;
+            alias __nlink_t = ulong;
             alias __uid_t = uint;
             alias __gid_t = uint;
             alias __off_t = c_long;
             alias __off64_t = long;
-            alias __blksize_t = int;
+            alias __blksize_t = c_long;
             alias __blkcnt_t = c_long;
             alias __blkcnt64_t = long;
             alias __timespec = timespec;
diff --git a/libphobos/libdruntime/rt/sections_elf_shared.d b/libphobos/libdruntime/rt/sections_elf_shared.d
index d4e1ff07699..5cc7a866fcb 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/libphobos/src/std/outbuffer.d b/libphobos/src/std/outbuffer.d
index 1d594982cc1..e9301181640 100644
--- a/libphobos/src/std/outbuffer.d
+++ b/libphobos/src/std/outbuffer.d
@@ -408,11 +408,17 @@ class OutBuffer
   {
     OutBuffer buf = new OutBuffer();
     "hello"w.copy(buf);
-    assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(LittleEndian)
+        assert(buf.toBytes() == "h\x00e\x00l\x00l\x00o\x00");
+    version(BigEndian)
+        assert(buf.toBytes() == "\x00h\x00e\x00l\x00l\x00o");
   }
   {
     OutBuffer buf = new OutBuffer();
     "hello"d.copy(buf);
-    assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(LittleEndian)
+        assert(buf.toBytes() == "h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o\x00\x00\x00");
+    version(BigEndian)
+        assert(buf.toBytes() == "\x00\x00\x00h\x00\x00\x00e\x00\x00\x00l\x00\x00\x00l\x00\x00\x00o");
   }
 }
diff --git a/libphobos/src/std/uni.d b/libphobos/src/std/uni.d
index 5f24ad16be5..baee073bfc2 100644
--- a/libphobos/src/std/uni.d
+++ b/libphobos/src/std/uni.d
@@ -770,6 +770,8 @@ version (X86)
     enum hasUnalignedReads = true;
 else version (X86_64)
     enum hasUnalignedReads = true;
+else version (SystemZ)
+    enum hasUnalignedReads = true;
 else
     enum hasUnalignedReads = false; // better be safe then sorry
 
@@ -1245,8 +1247,13 @@ pure nothrow:
 
         T opIndex(size_t idx) inout
         {
-            return __ctfe ? simpleIndex(idx) :
+            T ret;
+            version (LittleEndian)
+                ret = __ctfe ? simpleIndex(idx) :
                 cast(inout(T))(cast(U*) origin)[idx];
+            else
+                ret = simpleIndex (idx);
+            return ret;
         }
 
         static if (isBitPacked!T) // lack of user-defined implicit conversion
@@ -1259,10 +1266,15 @@ pure nothrow:
 
         void opIndexAssign(TypeOfBitPacked!T val, size_t idx)
         {
-            if (__ctfe)
-                simpleWrite(val, idx);
-            else
-                (cast(U*) origin)[idx] = cast(U) val;
+          version (LittleEndian)
+            {
+              if (__ctfe)
+                  simpleWrite(val, idx);
+              else
+                  (cast(U*) origin)[idx] = cast(U) val;
+            }
+          else
+              simpleWrite(val, idx);
         }
     }
     else
diff --git a/libphobos/src/std/xml.d b/libphobos/src/std/xml.d
index 770c56fdbfb..a0c5349d013 100644
--- a/libphobos/src/std/xml.d
+++ b/libphobos/src/std/xml.d
@@ -2192,6 +2192,8 @@ private
         catch (Err e) { fail(e); }
     }
 
+    import core.sys.posix.sys.types : ssize_t;
+
     void checkChars(ref string s) @safe pure // rule 2
     {
         // TO DO - Fix std.utf stride and decode functions, then use those
@@ -2201,8 +2203,8 @@ private
         mixin Check!("Chars");
 
         dchar c;
-        int n = -1;
-        foreach (int i,dchar d; s)
+        ssize_t n = -1;
+        foreach (size_t i,dchar d; s)
         {
             if (!isChar(d))
             {
@@ -2238,8 +2240,11 @@ private
         mixin Check!("Name");
 
         if (s.length == 0) fail();
-        int n;
-        foreach (int i,dchar c;s)
+        ssize_t n;
+        // i must not be smaller than size_t because size_t is used internally
+        // in aApply.d and it will be cast e.g. to (int *) which fails on
+        // big-endian machines.
+        foreach (size_t i,dchar c;s)
         {
             if (c == '_' || c == ':' || isLetter(c)) continue;
             if (i == 0) fail();
diff --git a/libphobos/testsuite/libphobos.typeinfo/struct-align.d b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
new file mode 100644
index 00000000000..72866517481
--- /dev/null
+++ b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
@@ -0,0 +1,13 @@
+module structalign;
+
+void main ()
+{
+    struct K { int *a; };
+    K k;
+    auto ti = typeid (k);
+
+    assert (ti.flags () == 1);
+
+    auto ti2 = typeid (k.a);
+    assert (ti.talign () == ti2.talign ());
+}
Iain Buclaw April 22, 2019, 2:01 p.m. | #18
On Thu, 18 Apr 2019 at 16:55, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> Hi Rainer,

>

> > I noticed you missed one piece of Iain's typeinfo.cc patch, btw.:

> >

> > diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc

> > --- a/gcc/d/typeinfo.cc

> > +++ b/gcc/d/typeinfo.cc

> > @@ -886,7 +886,7 @@ public:

> >       if (cd->isCOMinterface ())

> >         flags |= ClassFlags::isCOMclass;

> >

> > -     this->layout_field (build_integer_cst (flags));

> > +     this->layout_field (build_integer_cst (flags, d_uint_type));

> >

> >       /* void *deallocator;

> >          OffsetTypeInfo[] m_offTi;  (not implemented)

>

> thanks for catching this.  I amended the patch and ran the D test suite

> on S/390 and i386 one more time.

>

> For S/390 the number of FAILs is unchanged

>

>                 === libphobos Summary ===

>

> # of expected passes            380

> # of unexpected failures        30

>

> Some of the FAILs are still a little worrying, like tests for "-shared"

> which I haven't looked at at all so far.  Still, it's better than the

> >200 before.

>

> On i386 I see no FAILs with the patch.

>


Thanks, I've upstreamed and committed the dmd, druntime, and phobos
parts in r270485, r270490, and r270491 respectively.

Of the remaining patch, the sections module is now
libdruntime/gcc/sections/elf_shared.d.

Other than that, all looks OK.

--
Iain
---
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..865fde2c863 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
     flags |= ClassFlags::noPointers;

     Lhaspointers:
-    this->layout_field (size_int (flags));
+    this->layout_field (build_integer_cst (flags, d_uint_type));

     /* void *deallocator;  */
     tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
     if (cd->isCOMinterface ())
       flags |= ClassFlags::isCOMclass;

-    this->layout_field (size_int (flags));
+    this->layout_field (build_integer_cst (flags, d_uint_type));

     /* void *deallocator;
        OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));

     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);

     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));

     if (global.params.is64bit)
       {
@@ -1489,8 +1489,8 @@ create_typeinfo (Type *type, Module *mod)
                       array_type_node, array_type_node,
                       ptr_type_node, ptr_type_node,
                       ptr_type_node, ptr_type_node,
-                      size_type_node, ptr_type_node,
-                      ptr_type_node, size_type_node,
+                      d_uint_type, ptr_type_node,
+                      ptr_type_node, d_uint_type,
                       ptr_type_node, argtype, argtype, NULL);
         }
       t->vtinfo = TypeInfoStructDeclaration::create (t);
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index e36a2585027..8d9a5868831 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -890,12 +890,17 @@ struct S186
     }
 }

+static if (size_t.sizeof == 8)
+     size_t checkval = 0x0200000000000002;
+static if (size_t.sizeof == 4)
+     size_t checkval = 0x02000002;
+
 void check186(in S186 obj, byte fieldB)
 {
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
     assert(fieldB == 0);
 }

@@ -907,7 +912,7 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);

     obj = S186(val);
     check186(obj, obj.fieldB);
@@ -915,12 +920,12 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 }

 void test186()
 {
-    test186a(2);
+    test186a(checkval);
 }

 /******************************************/
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d
index 812b36649aa..7d0aa0168c0 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/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..5cc7a866fcb 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/libphobos/testsuite/libphobos.typeinfo/struct-align.d
b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
new file mode 100644
index 00000000000..72866517481
--- /dev/null
+++ b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
@@ -0,0 +1,13 @@
+module structalign;
+
+void main ()
+{
+    struct K { int *a; };
+    K k;
+    auto ti = typeid (k);
+
+    assert (ti.flags () == 1);
+
+    auto ti2 = typeid (k.a);
+    assert (ti.talign () == ti2.talign ());
+}
Robin Dapp April 24, 2019, 8:04 a.m. | #19
Hi,

the attached patch is against the current HEAD, fixing one additional
test case.

Parallel testing does not seem to work anymore.  Adding the following
define for ${PWD_COMMAND} makes it work again.


diff --git a/libphobos/testsuite/Makefile.in
b/libphobos/testsuite/Makefile.in
index 26ed875d964..ae1cf83615e 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -303,6 +303,7 @@ check_DEJAGNU_libphobos_targets = $(addprefix
check-DEJAGNUlibphobos,$(check_p_s
 AM_MAKEFLAGS = "EXEEXT=$(EXEEXT)"
 CLEANFILES = *.exe *.log *.o *.sum site.exp
 all: all-am
+PWD_COMMAND = $${PWDCMD-pwd}

 .SUFFIXES:
 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am
$(am__configure_deps)


Regards
 Robin

--

gcc/d/ChangeLog:

2019-04-24  Robin Dapp  <rdapp@linux.ibm.com>

	* typeinfo.cc (create_typeinfo): Set fields with proper length.

gcc/testsuite/ChangeLog:

2019-04-24  Robin Dapp  <rdapp@linux.ibm.com>

	* gdc.dg/runnable.d: Add Big Endian handling.
	* gdc.dg/simd.d: Likewise.
	* gdc.test/runnable/test42.d: Likewise.

libphobos/ChangeLog:

2019-04-24  Robin Dapp  <rdapp@linux.ibm.com>

	* configure.tgt: Add S390.
	* libdruntime/gcc/sections/elf_shared.d: Add TLS handling for S390.
	* testsuite/libphobos.typeinfo/struct-align.d: New test.
diff --git a/gcc/d/typeinfo.cc b/gcc/d/typeinfo.cc
index dac66acdcd4..865fde2c863 100644
--- a/gcc/d/typeinfo.cc
+++ b/gcc/d/typeinfo.cc
@@ -830,7 +830,7 @@ public:
 	flags |= ClassFlags::noPointers;
 
     Lhaspointers:
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;  */
 	tree ddtor = (cd->aggDelete)
@@ -886,7 +886,7 @@ public:
 	if (cd->isCOMinterface ())
 	  flags |= ClassFlags::isCOMclass;
 
-	this->layout_field (size_int (flags));
+	this->layout_field (build_integer_cst (flags, d_uint_type));
 
 	/* void *deallocator;
 	   OffsetTypeInfo[] m_offTi;  (not implemented)
@@ -1019,7 +1019,7 @@ public:
     StructFlags::Type m_flags = 0;
     if (ti->hasPointers ())
       m_flags |= StructFlags::hasPointers;
-    this->layout_field (size_int (m_flags));
+    this->layout_field (build_integer_cst (m_flags, d_uint_type));
 
     /* void function(void*) xdtor;  */
     tree dtor = (sd->dtor) ? build_address (get_symbol_decl (sd->dtor))
@@ -1033,7 +1033,7 @@ public:
       this->layout_field (null_pointer_node);
 
     /* uint m_align;  */
-    this->layout_field (size_int (ti->alignsize ()));
+    this->layout_field (build_integer_cst (ti->alignsize (), d_uint_type));
 
     if (global.params.is64bit)
       {
@@ -1489,8 +1489,8 @@ create_typeinfo (Type *type, Module *mod)
 				      array_type_node, array_type_node,
 				      ptr_type_node, ptr_type_node,
 				      ptr_type_node, ptr_type_node,
-				      size_type_node, ptr_type_node,
-				      ptr_type_node, size_type_node,
+				      d_uint_type, ptr_type_node,
+				      ptr_type_node, d_uint_type,
 				      ptr_type_node, argtype, argtype, NULL);
 	    }
 	  t->vtinfo = TypeInfoStructDeclaration::create (t);
diff --git a/gcc/testsuite/gdc.dg/runnable.d b/gcc/testsuite/gdc.dg/runnable.d
index e36a2585027..fc5fd14c7d9 100644
--- a/gcc/testsuite/gdc.dg/runnable.d
+++ b/gcc/testsuite/gdc.dg/runnable.d
@@ -890,12 +890,18 @@ struct S186
     }
 }
 
+static if (size_t.sizeof == 8)
+     size_t checkval = 0x0200000000000002;
+static if (size_t.sizeof == 4)
+     size_t checkval = 0x02000002;
+
+
 void check186(in S186 obj, byte fieldB)
 {
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
     assert(fieldB == 0);
 }
 
@@ -907,7 +913,7 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 
     obj = S186(val);
     check186(obj, obj.fieldB);
@@ -915,12 +921,12 @@ void test186a(size_t val)
     assert(obj.fieldA == 2);
     assert(obj.fieldB == 0);
     assert(obj.fieldC == 0);
-    assert(obj._complete == 2);
+    assert(obj._complete == checkval);
 }
 
 void test186()
 {
-    test186a(2);
+    test186a(checkval);
 }
 
 /******************************************/
diff --git a/gcc/testsuite/gdc.dg/simd.d b/gcc/testsuite/gdc.dg/simd.d
index 812b36649aa..7d0aa0168c0 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/test42.d b/gcc/testsuite/gdc.test/runnable/test42.d
index 87ee7a8e73a..c3cf91167b2 100644
--- a/gcc/testsuite/gdc.test/runnable/test42.d
+++ b/gcc/testsuite/gdc.test/runnable/test42.d
@@ -4963,20 +4963,34 @@ struct Test244 {
 
 int noswap245(ubyte *data)
 {
+  version (LittleEndian)
     return
         (data[0]<<  0) |
         (data[1]<<  8) |
         (data[2]<< 16) |
         (data[3]<< 24);
+  version (BigEndian)
+    return
+        (data[0]<< 24) |
+        (data[1]<< 16) |
+        (data[2]<<  8) |
+        (data[3]<<  0);
 }
 
 int bswap245(ubyte *data)
 {
+  version (LittleEndian)
     return
         (data[0]<< 24) |
         (data[1]<< 16) |
-        (data[2]<< 8 ) |
-        (data[3]<< 0 );
+        (data[2]<<  8) |
+        (data[3]<<  0);
+  version (BigEndian)
+    return
+        (data[0]<<  0) |
+        (data[1]<<  8) |
+        (data[2]<< 16) |
+        (data[3]<< 24);
 }
 
 void test245()
diff --git a/libphobos/configure.tgt b/libphobos/configure.tgt
index b30f0858108..9c6e1a04cc7 100644
--- a/libphobos/configure.tgt
+++ b/libphobos/configure.tgt
@@ -41,4 +41,7 @@ case "${target}" in
   x86_64-*-solaris2.11* | i?86-*-solaris2.11*)
 	LIBPHOBOS_SUPPORTED=yes
 	;;
+  s390*-linux*)
+	LIBPHOBOS_SUPPORTED=yes
+        ;;
 esac
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 4cf5a233fc4..a957e551c14 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -980,6 +980,7 @@ struct tls_index
 }
 
 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.
@@ -1013,6 +1014,8 @@ else version (MIPS32)
     enum TLS_DTV_OFFSET = 0x8000;
 else version (MIPS64)
     enum TLS_DTV_OFFSET = 0x8000;
+else version (SystemZ)
+    enum TLS_DTV_OFFSET = 0;
 else
     static assert( false, "Platform not supported." );
 
@@ -1029,5 +1032,14 @@ 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)
+      {
+          import gcc.builtins;
+          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/libphobos/testsuite/libphobos.typeinfo/struct-align.d b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
new file mode 100644
index 00000000000..72866517481
--- /dev/null
+++ b/libphobos/testsuite/libphobos.typeinfo/struct-align.d
@@ -0,0 +1,13 @@
+module structalign;
+
+void main ()
+{
+    struct K { int *a; };
+    K k;
+    auto ti = typeid (k);
+
+    assert (ti.flags () == 1);
+
+    auto ti2 = typeid (k.a);
+    assert (ti.talign () == ti2.talign ());
+}
Iain Buclaw April 24, 2019, 9:20 a.m. | #20
On Wed, 24 Apr 2019 at 10:05, Robin Dapp <rdapp@linux.ibm.com> wrote:
>

> Hi,

>

> the attached patch is against the current HEAD, fixing one additional

> test case.

>


Thanks, this has been committed.

> Parallel testing does not seem to work anymore.  Adding the following

> define for ${PWD_COMMAND} makes it work again.

>

>


Looks OK to me, I guess r270303 would be the introducer of what you're seeing.

This would be the complete patch for that.

libphobos/ChangeLog:

       * testsuite/Makefile.am: Set PWD_COMMAND.
       * testsuite/Makefile.in: Regenerate.

diff --git a/libphobos/testsuite/Makefile.am b/libphobos/testsuite/Makefile.am
index 55b2ba42640..70b105d4014 100644
--- a/libphobos/testsuite/Makefile.am
+++ b/libphobos/testsuite/Makefile.am
@@ -27,6 +27,8 @@ _RUNTEST = $(shell if test -f
$(top_srcdir)/../dejagnu/runtest; then \
             echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)
 RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir

+PWD_COMMAND = $${PWDCMD-pwd}
+
 check_p_subno=$(word 2,$(subst _, ,$*))
 check_p_numbers0:=1 2 3 4 5 6 7 8 9
 check_p_numbers1:=0 $(check_p_numbers0)
diff --git a/libphobos/testsuite/Makefile.in b/libphobos/testsuite/Makefile.in
index 26ed875d964..efbd884d7ae 100644
--- a/libphobos/testsuite/Makefile.in
+++ b/libphobos/testsuite/Makefile.in
@@ -289,6 +289,7 @@ _RUNTEST = $(shell if test -f
$(top_srcdir)/../dejagnu/runtest; then \
             echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi)

 RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
+PWD_COMMAND = $${PWDCMD-pwd}
 check_p_subno = $(word 2,$(subst _, ,$*))
 check_p_numbers0 := 1 2 3 4 5 6 7 8 9
 check_p_numbers1 := 0 $(check_p_numbers0)
Matthias Klose April 27, 2019, 9:26 a.m. | #21
On 15.03.19 16:49, Robin Dapp wrote:
> 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.


this now fails on trunk and the gcc-9-branch with a multilib build:


/<<PKGBUILDDIR>>/src/libphobos/libdruntime/core/sys/posix/ucontext.d:769:9:
error: static assert  "unimpleme
nted"
  769 |         static assert(0, "unimplemented");
      |         ^
make[10]: *** [Makefile:2149: core/thread.lo] Error 1
make[10]: Leaving directory
'/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'
make[9]: *** [Makefile:473: all-recursive] Error 1
make[10]: *** [Makefile:2149: core/thread.lo] Error 1
make[10]: Leaving directory
'/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'
make[9]: *** [Makefile:473: all-recursive] Error 1
Jakub Jelinek April 27, 2019, 10:24 a.m. | #22
On Sat, Apr 27, 2019 at 11:26:15AM +0200, Matthias Klose wrote:
> On 15.03.19 16:49, Robin Dapp wrote:

> > 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.

> 

> this now fails on trunk and the gcc-9-branch with a multilib build:

> 

> 

> /<<PKGBUILDDIR>>/src/libphobos/libdruntime/core/sys/posix/ucontext.d:769:9:

> error: static assert  "unimpleme

> nted"

>   769 |         static assert(0, "unimplemented");

>       |         ^

> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> make[10]: Leaving directory

> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> make[9]: *** [Makefile:473: all-recursive] Error 1

> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> make[10]: Leaving directory

> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> make[9]: *** [Makefile:473: all-recursive] Error 1


Ugh, can we disable D for GCC 9.1 on s390x then, on the trunk look through
all files that only use version (SystemZ) and don't use version (S390) at
least
find -type f | xargs grep -l SystemZ | xargs grep -L S390
./src/std/uni.d
./src/std/math.d
./src/std/experimental/allocator/building_blocks/region.d
./libdruntime/gcc/sections/elf_shared.d
./libdruntime/core/sys/linux/link.d
./libdruntime/core/sys/posix/setjmp.d
./libdruntime/core/sys/posix/ucontext.d
./libdruntime/core/sys/posix/sys/stat.d
and make sure it works also for s390 31-bit and finally backport to 9.2?

E.g. in src/std/math.d I wonder if it just shouldn't be done through
version (S390)      version = IBMZ_Any;
version (SystemZ)   version = IBMZ_Any;
and using later version (IBMZ_Any) instead of version (SystemZ).  Guess
in various other spots, except for those where structure sizes are needed.

Robin, have you been testing with --disable-multilib or something similar?

	Jakub
Iain Buclaw April 27, 2019, 12:08 p.m. | #23
On Sat, 27 Apr 2019 at 12:24, Jakub Jelinek <jakub@redhat.com> wrote:
>

> On Sat, Apr 27, 2019 at 11:26:15AM +0200, Matthias Klose wrote:

> > On 15.03.19 16:49, Robin Dapp wrote:

> > > 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.

> >

> > this now fails on trunk and the gcc-9-branch with a multilib build:

> >

> >

> > /<<PKGBUILDDIR>>/src/libphobos/libdruntime/core/sys/posix/ucontext.d:769:9:

> > error: static assert  "unimpleme

> > nted"

> >   769 |         static assert(0, "unimplemented");

> >       |         ^

> > make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> > make[10]: Leaving directory

> > '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> > make[9]: *** [Makefile:473: all-recursive] Error 1

> > make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> > make[10]: Leaving directory

> > '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> > make[9]: *** [Makefile:473: all-recursive] Error 1

>

> Ugh, can we disable D for GCC 9.1 on s390x then, on the trunk look through

> all files that only use version (SystemZ) and don't use version (S390) at

> least

> find -type f | xargs grep -l SystemZ | xargs grep -L S390

> ./src/std/uni.d

> ./src/std/math.d

> ./src/std/experimental/allocator/building_blocks/region.d

> ./libdruntime/gcc/sections/elf_shared.d

> ./libdruntime/core/sys/linux/link.d

> ./libdruntime/core/sys/posix/setjmp.d

> ./libdruntime/core/sys/posix/ucontext.d

> ./libdruntime/core/sys/posix/sys/stat.d

> and make sure it works also for s390 31-bit and finally backport to 9.2?

>

> E.g. in src/std/math.d I wonder if it just shouldn't be done through

> version (S390)      version = IBMZ_Any;

> version (SystemZ)   version = IBMZ_Any;

> and using later version (IBMZ_Any) instead of version (SystemZ).  Guess

> in various other spots, except for those where structure sizes are needed.

>

> Robin, have you been testing with --disable-multilib or something similar?

>


I built all compilers last night from config-list.mk, so I had a ready
cross compiler available.  With the following patch, all compiles
successfully with -fsyntax-only for both s390x-linux and s390-linux,
though checking on native hardware would be preferred.

-- 
Iain
---
diff --git a/libphobos/libdruntime/core/sys/linux/link.d b/libphobos/libdruntime/core/sys/linux/link.d
index b57b5e5d00f..e242d2b2876 100644
--- a/libphobos/libdruntime/core/sys/linux/link.d
+++ b/libphobos/libdruntime/core/sys/linux/link.d
@@ -18,8 +18,10 @@ version (PPC)     version = PPC_Any;
 version (PPC64)   version = PPC_Any;
 version (RISCV32) version = RISCV_Any;
 version (RISCV64) version = RISCV_Any;
+version (S390)    version = IBMZ_Any;
 version (SPARC)   version = SPARC_Any;
 version (SPARC64) version = SPARC_Any;
+version (SystemZ) version = IBMZ_Any;
 version (X86)     version = X86_Any;
 version (X86_64)  version = X86_Any;
 
@@ -71,11 +73,14 @@ else version (SPARC_Any)
     alias __WORDSIZE __ELF_NATIVE_CLASS;
     alias uint32_t Elf_Symndx;
 }
-else version (SystemZ)
+else version (IBMZ_Any)
 {
     // http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/s390/bits/elfclass.h
     alias __WORDSIZE __ELF_NATIVE_CLASS;
-    alias uint64_t Elf_Symndx;
+    static if (__WORDSIZE == 64)
+        alias uint64_t Elf_Symndx;
+    else
+        alias uint32_t Elf_Symndx;
 }
 else
     static assert(0, "unimplemented");
diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d
index 8b636683e3d..fcdbca496c4 100644
--- a/libphobos/libdruntime/core/sys/posix/setjmp.d
+++ b/libphobos/libdruntime/core/sys/posix/setjmp.d
@@ -153,6 +153,15 @@ version (CRuntime_Glibc)
         }
         alias __jmp_buf = __riscv_jmp_buf[1];
     }
+    else version (S390)
+    {
+        struct __s390_jmp_buf
+        {
+            c_long[10] __gregs;
+            c_long[4] __fpregs;
+        }
+        alias __jmp_buf = __s390_jmp_buf[1];
+    }
     else version (SystemZ)
     {
         struct __s390_jmp_buf
diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d
index 963a241f076..76e4460550d 100644
--- a/libphobos/libdruntime/core/sys/posix/sys/stat.d
+++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d
@@ -791,6 +791,82 @@ version (CRuntime_Glibc)
         }
         static assert(stat_t.sizeof == 144);
     }
+    else version (S390)
+    {
+        private
+        {
+            alias __dev_t = ulong;
+            alias __ino_t = c_ulong;
+            alias __ino64_t = ulong;
+            alias __mode_t = uint;
+            alias __nlink_t = uint;
+            alias __uid_t = uint;
+            alias __gid_t = uint;
+            alias __off_t = c_long;
+            alias __off64_t = long;
+            alias __blksize_t = c_long;
+            alias __blkcnt_t = c_long;
+            alias __blkcnt64_t = long;
+            alias __timespec = timespec;
+            alias __time_t = time_t;
+        }
+        struct stat_t
+        {
+            __dev_t st_dev;
+            uint __pad1;
+            static if (!__USE_FILE_OFFSET64)
+                __ino_t st_ino;
+            else
+                __ino_t __st_ino;
+            __mode_t st_mode;
+            __nlink_t st_nlink;
+            __uid_t st_uid;
+            __gid_t st_gid;
+            __dev_t st_rdev;
+            uint __pad2;
+            static if (!__USE_FILE_OFFSET64)
+                __off_t st_size;
+            else
+                __off64_t st_size;
+            __blksize_t st_blksize;
+            static if (!__USE_FILE_OFFSET64)
+                __blkcnt_t st_blocks;
+            else
+                __blkcnt64_t st_blocks;
+            static if (__USE_XOPEN2K8)
+            {
+                __timespec st_atim;
+                __timespec st_mtim;
+                __timespec st_ctim;
+                extern(D)
+                {
+                    @property ref time_t st_atime() { return st_atim.tv_sec; }
+                    @property ref time_t st_mtime() { return st_mtim.tv_sec; }
+                    @property ref time_t st_ctime() { return st_ctim.tv_sec; }
+                }
+            }
+            else
+            {
+                __time_t st_atime;
+                c_ulong st_atimensec;
+                __time_t st_mtime;
+                c_ulong st_mtimensec;
+                __time_t st_ctime;
+                c_ulong st_ctimensec;
+            }
+            static if (!__USE_FILE_OFFSET64)
+            {
+                c_ulong __glibc_reserved4;
+                c_ulong __glibc_reserved5;
+            }
+            else
+                __ino64_t st_ino;
+        }
+        static if (__USE_FILE_OFFSET64)
+            static assert(stat_t.sizeof == 104);
+        else
+            static assert(stat_t.sizeof == 88);
+    }
     else version (SystemZ)
     {
         private
diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d
index 6200bfc3fe2..d664f2e5e41 100644
--- a/libphobos/libdruntime/core/sys/posix/ucontext.d
+++ b/libphobos/libdruntime/core/sys/posix/ucontext.d
@@ -25,8 +25,10 @@ nothrow:
 
 version (RISCV32) version = RISCV_Any;
 version (RISCV64) version = RISCV_Any;
+version (S390)    version = IBMZ_Any;
 version (SPARC)   version = SPARC_Any;
 version (SPARC64) version = SPARC_Any;
+version (SystemZ) version = IBMZ_Any;
 version (X86)     version = X86_Any;
 version (X86_64)  version = X86_Any;
 
@@ -719,7 +721,7 @@ version (CRuntime_Glibc)
         alias greg_t = c_ulong;
         alias gregset_t = greg_t[NGREG];
     }
-    else version (SystemZ)
+    else version (IBMZ_Any)
     {
         public import core.sys.posix.signal : sigset_t;
 
diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d
index 1eafecdd322..7f9036bf505 100644
--- a/libphobos/libdruntime/gcc/sections/elf_shared.d
+++ b/libphobos/libdruntime/gcc/sections/elf_shared.d
@@ -24,6 +24,8 @@ module gcc.sections.elf_shared;
 
 version (RISCV32) version = RISCV_Any;
 version (RISCV64) version = RISCV_Any;
+version (S390)    version = IBMZ_Any;
+version (SystemZ) version = IBMZ_Any;
 
 version (CRuntime_Glibc) enum SharedELF = true;
 else version (CRuntime_Musl) enum SharedELF = true;
@@ -1060,7 +1062,7 @@ else version (MIPS32)
     enum TLS_DTV_OFFSET = 0x8000;
 else version (MIPS64)
     enum TLS_DTV_OFFSET = 0x8000;
-else version (SystemZ)
+else version (IBMZ_Any)
     enum TLS_DTV_OFFSET = 0x0;
 else
     static assert( false, "Platform not supported." );
@@ -1070,20 +1072,25 @@ void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc
     if (mod == 0)
         return null;
 
-    version (Solaris)
+    version (GNU_EMUTLS)
+        return null;    // Handled in scanTLSRanges().
+    else
     {
-        static if (!OS_Have_Dlpi_Tls_Modid)
-            mod -= 1;
-    }
+        version (Solaris)
+        {
+            static if (!OS_Have_Dlpi_Tls_Modid)
+                mod -= 1;
+        }
 
-    // base offset
-    auto ti = tls_index(mod, 0);
-    version (SystemZ)
-    {
-        auto idx = cast(void *)__tls_get_addr_internal(&ti)
-            + cast(ulong)__builtin_thread_pointer();
-        return idx[0 .. sz];
+        // base offset
+        auto ti = tls_index(mod, 0);
+        version (IBMZ_Any)
+        {
+            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];
     }
-    else
-        return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];
 }
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 6dec9cee9a0..7bc94220fc7 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -160,8 +160,10 @@ version (MIPS32)    version = MIPS_Any;
 version (MIPS64)    version = MIPS_Any;
 version (AArch64)   version = ARM_Any;
 version (ARM)       version = ARM_Any;
+version (S390)      version = IBMZ_Any;
 version (SPARC)     version = SPARC_Any;
 version (SPARC64)   version = SPARC_Any;
+version (SystemZ)   version = IBMZ_Any;
 version (RISCV32)   version = RISCV_Any;
 version (RISCV64)   version = RISCV_Any;
 
@@ -5235,7 +5237,7 @@ struct FloatingPointControl
                                  | inexactException,
         }
     }
-    else version (SystemZ)
+    else version (IBMZ_Any)
     {
         enum : ExceptionMask
         {
@@ -5373,7 +5375,7 @@ private:
     {
         alias ControlState = ulong;
     }
-    else version (SystemZ)
+    else version (IBMZ_Any)
     {
         alias ControlState = uint;
     }
Jakub Jelinek April 27, 2019, 8:03 p.m. | #24
On Sat, Apr 27, 2019 at 02:08:06PM +0200, Iain Buclaw wrote:
> I built all compilers last night from config-list.mk, so I had a ready

> cross compiler available.  With the following patch, all compiles

> successfully with -fsyntax-only for both s390x-linux and s390-linux,

> though checking on native hardware would be preferred.


I can confirm s390x-linux with
--enable-multilib --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
fails to bootstrap on gcc-9-branch without this patch and succeeds to
bootstrap with this patch.
The patch is ok to backport to gcc-9-branch once you commit it to trunk
(would be nice if you could do it soon, so that we don't ship 9.1 broken on
s390x-linux).

> diff --git a/libphobos/libdruntime/core/sys/linux/link.d b/libphobos/libdruntime/core/sys/linux/link.d

> index b57b5e5d00f..e242d2b2876 100644

> --- a/libphobos/libdruntime/core/sys/linux/link.d

> +++ b/libphobos/libdruntime/core/sys/linux/link.d

> @@ -18,8 +18,10 @@ version (PPC)     version = PPC_Any;

>  version (PPC64)   version = PPC_Any;

>  version (RISCV32) version = RISCV_Any;

>  version (RISCV64) version = RISCV_Any;

> +version (S390)    version = IBMZ_Any;

>  version (SPARC)   version = SPARC_Any;

>  version (SPARC64) version = SPARC_Any;

> +version (SystemZ) version = IBMZ_Any;

>  version (X86)     version = X86_Any;

>  version (X86_64)  version = X86_Any;

>  

> @@ -71,11 +73,14 @@ else version (SPARC_Any)

>      alias __WORDSIZE __ELF_NATIVE_CLASS;

>      alias uint32_t Elf_Symndx;

>  }

> -else version (SystemZ)

> +else version (IBMZ_Any)

>  {

>      // http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/s390/bits/elfclass.h

>      alias __WORDSIZE __ELF_NATIVE_CLASS;

> -    alias uint64_t Elf_Symndx;

> +    static if (__WORDSIZE == 64)

> +        alias uint64_t Elf_Symndx;

> +    else

> +        alias uint32_t Elf_Symndx;

>  }

>  else

>      static assert(0, "unimplemented");

> diff --git a/libphobos/libdruntime/core/sys/posix/setjmp.d b/libphobos/libdruntime/core/sys/posix/setjmp.d

> index 8b636683e3d..fcdbca496c4 100644

> --- a/libphobos/libdruntime/core/sys/posix/setjmp.d

> +++ b/libphobos/libdruntime/core/sys/posix/setjmp.d

> @@ -153,6 +153,15 @@ version (CRuntime_Glibc)

>          }

>          alias __jmp_buf = __riscv_jmp_buf[1];

>      }

> +    else version (S390)

> +    {

> +        struct __s390_jmp_buf

> +        {

> +            c_long[10] __gregs;

> +            c_long[4] __fpregs;

> +        }

> +        alias __jmp_buf = __s390_jmp_buf[1];

> +    }

>      else version (SystemZ)

>      {

>          struct __s390_jmp_buf

> diff --git a/libphobos/libdruntime/core/sys/posix/sys/stat.d b/libphobos/libdruntime/core/sys/posix/sys/stat.d

> index 963a241f076..76e4460550d 100644

> --- a/libphobos/libdruntime/core/sys/posix/sys/stat.d

> +++ b/libphobos/libdruntime/core/sys/posix/sys/stat.d

> @@ -791,6 +791,82 @@ version (CRuntime_Glibc)

>          }

>          static assert(stat_t.sizeof == 144);

>      }

> +    else version (S390)

> +    {

> +        private

> +        {

> +            alias __dev_t = ulong;

> +            alias __ino_t = c_ulong;

> +            alias __ino64_t = ulong;

> +            alias __mode_t = uint;

> +            alias __nlink_t = uint;

> +            alias __uid_t = uint;

> +            alias __gid_t = uint;

> +            alias __off_t = c_long;

> +            alias __off64_t = long;

> +            alias __blksize_t = c_long;

> +            alias __blkcnt_t = c_long;

> +            alias __blkcnt64_t = long;

> +            alias __timespec = timespec;

> +            alias __time_t = time_t;

> +        }

> +        struct stat_t

> +        {

> +            __dev_t st_dev;

> +            uint __pad1;

> +            static if (!__USE_FILE_OFFSET64)

> +                __ino_t st_ino;

> +            else

> +                __ino_t __st_ino;

> +            __mode_t st_mode;

> +            __nlink_t st_nlink;

> +            __uid_t st_uid;

> +            __gid_t st_gid;

> +            __dev_t st_rdev;

> +            uint __pad2;

> +            static if (!__USE_FILE_OFFSET64)

> +                __off_t st_size;

> +            else

> +                __off64_t st_size;

> +            __blksize_t st_blksize;

> +            static if (!__USE_FILE_OFFSET64)

> +                __blkcnt_t st_blocks;

> +            else

> +                __blkcnt64_t st_blocks;

> +            static if (__USE_XOPEN2K8)

> +            {

> +                __timespec st_atim;

> +                __timespec st_mtim;

> +                __timespec st_ctim;

> +                extern(D)

> +                {

> +                    @property ref time_t st_atime() { return st_atim.tv_sec; }

> +                    @property ref time_t st_mtime() { return st_mtim.tv_sec; }

> +                    @property ref time_t st_ctime() { return st_ctim.tv_sec; }

> +                }

> +            }

> +            else

> +            {

> +                __time_t st_atime;

> +                c_ulong st_atimensec;

> +                __time_t st_mtime;

> +                c_ulong st_mtimensec;

> +                __time_t st_ctime;

> +                c_ulong st_ctimensec;

> +            }

> +            static if (!__USE_FILE_OFFSET64)

> +            {

> +                c_ulong __glibc_reserved4;

> +                c_ulong __glibc_reserved5;

> +            }

> +            else

> +                __ino64_t st_ino;

> +        }

> +        static if (__USE_FILE_OFFSET64)

> +            static assert(stat_t.sizeof == 104);

> +        else

> +            static assert(stat_t.sizeof == 88);

> +    }

>      else version (SystemZ)

>      {

>          private

> diff --git a/libphobos/libdruntime/core/sys/posix/ucontext.d b/libphobos/libdruntime/core/sys/posix/ucontext.d

> index 6200bfc3fe2..d664f2e5e41 100644

> --- a/libphobos/libdruntime/core/sys/posix/ucontext.d

> +++ b/libphobos/libdruntime/core/sys/posix/ucontext.d

> @@ -25,8 +25,10 @@ nothrow:

>  

>  version (RISCV32) version = RISCV_Any;

>  version (RISCV64) version = RISCV_Any;

> +version (S390)    version = IBMZ_Any;

>  version (SPARC)   version = SPARC_Any;

>  version (SPARC64) version = SPARC_Any;

> +version (SystemZ) version = IBMZ_Any;

>  version (X86)     version = X86_Any;

>  version (X86_64)  version = X86_Any;

>  

> @@ -719,7 +721,7 @@ version (CRuntime_Glibc)

>          alias greg_t = c_ulong;

>          alias gregset_t = greg_t[NGREG];

>      }

> -    else version (SystemZ)

> +    else version (IBMZ_Any)

>      {

>          public import core.sys.posix.signal : sigset_t;

>  

> diff --git a/libphobos/libdruntime/gcc/sections/elf_shared.d b/libphobos/libdruntime/gcc/sections/elf_shared.d

> index 1eafecdd322..7f9036bf505 100644

> --- a/libphobos/libdruntime/gcc/sections/elf_shared.d

> +++ b/libphobos/libdruntime/gcc/sections/elf_shared.d

> @@ -24,6 +24,8 @@ module gcc.sections.elf_shared;

>  

>  version (RISCV32) version = RISCV_Any;

>  version (RISCV64) version = RISCV_Any;

> +version (S390)    version = IBMZ_Any;

> +version (SystemZ) version = IBMZ_Any;

>  

>  version (CRuntime_Glibc) enum SharedELF = true;

>  else version (CRuntime_Musl) enum SharedELF = true;

> @@ -1060,7 +1062,7 @@ else version (MIPS32)

>      enum TLS_DTV_OFFSET = 0x8000;

>  else version (MIPS64)

>      enum TLS_DTV_OFFSET = 0x8000;

> -else version (SystemZ)

> +else version (IBMZ_Any)

>      enum TLS_DTV_OFFSET = 0x0;

>  else

>      static assert( false, "Platform not supported." );

> @@ -1070,20 +1072,25 @@ void[] getTLSRange(size_t mod, size_t sz) nothrow @nogc

>      if (mod == 0)

>          return null;

>  

> -    version (Solaris)

> +    version (GNU_EMUTLS)

> +        return null;    // Handled in scanTLSRanges().

> +    else

>      {

> -        static if (!OS_Have_Dlpi_Tls_Modid)

> -            mod -= 1;

> -    }

> +        version (Solaris)

> +        {

> +            static if (!OS_Have_Dlpi_Tls_Modid)

> +                mod -= 1;

> +        }

>  

> -    // base offset

> -    auto ti = tls_index(mod, 0);

> -    version (SystemZ)

> -    {

> -        auto idx = cast(void *)__tls_get_addr_internal(&ti)

> -            + cast(ulong)__builtin_thread_pointer();

> -        return idx[0 .. sz];

> +        // base offset

> +        auto ti = tls_index(mod, 0);

> +        version (IBMZ_Any)

> +        {

> +            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];

>      }

> -    else

> -        return (__tls_get_addr(&ti)-TLS_DTV_OFFSET)[0 .. sz];

>  }

> diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d

> index 6dec9cee9a0..7bc94220fc7 100644

> --- a/libphobos/src/std/math.d

> +++ b/libphobos/src/std/math.d

> @@ -160,8 +160,10 @@ version (MIPS32)    version = MIPS_Any;

>  version (MIPS64)    version = MIPS_Any;

>  version (AArch64)   version = ARM_Any;

>  version (ARM)       version = ARM_Any;

> +version (S390)      version = IBMZ_Any;

>  version (SPARC)     version = SPARC_Any;

>  version (SPARC64)   version = SPARC_Any;

> +version (SystemZ)   version = IBMZ_Any;

>  version (RISCV32)   version = RISCV_Any;

>  version (RISCV64)   version = RISCV_Any;

>  

> @@ -5235,7 +5237,7 @@ struct FloatingPointControl

>                                   | inexactException,

>          }

>      }

> -    else version (SystemZ)

> +    else version (IBMZ_Any)

>      {

>          enum : ExceptionMask

>          {

> @@ -5373,7 +5375,7 @@ private:

>      {

>          alias ControlState = ulong;

>      }

> -    else version (SystemZ)

> +    else version (IBMZ_Any)

>      {

>          alias ControlState = uint;

>      }



	Jakub
Matthias Klose April 29, 2019, 4:11 a.m. | #25
On 27.04.19 14:08, Iain Buclaw wrote:
> On Sat, 27 Apr 2019 at 12:24, Jakub Jelinek <jakub@redhat.com> wrote:

>>

>> On Sat, Apr 27, 2019 at 11:26:15AM +0200, Matthias Klose wrote:

>>> On 15.03.19 16:49, Robin Dapp wrote:

>>>> 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.

>>>

>>> this now fails on trunk and the gcc-9-branch with a multilib build:

>>>

>>>

>>> /<<PKGBUILDDIR>>/src/libphobos/libdruntime/core/sys/posix/ucontext.d:769:9:

>>> error: static assert  "unimpleme

>>> nted"

>>>   769 |         static assert(0, "unimplemented");

>>>       |         ^

>>> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

>>> make[10]: Leaving directory

>>> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

>>> make[9]: *** [Makefile:473: all-recursive] Error 1

>>> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

>>> make[10]: Leaving directory

>>> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

>>> make[9]: *** [Makefile:473: all-recursive] Error 1

>>

>> Ugh, can we disable D for GCC 9.1 on s390x then, on the trunk look through

>> all files that only use version (SystemZ) and don't use version (S390) at

>> least

>> find -type f | xargs grep -l SystemZ | xargs grep -L S390

>> ./src/std/uni.d

>> ./src/std/math.d

>> ./src/std/experimental/allocator/building_blocks/region.d

>> ./libdruntime/gcc/sections/elf_shared.d

>> ./libdruntime/core/sys/linux/link.d

>> ./libdruntime/core/sys/posix/setjmp.d

>> ./libdruntime/core/sys/posix/ucontext.d

>> ./libdruntime/core/sys/posix/sys/stat.d

>> and make sure it works also for s390 31-bit and finally backport to 9.2?

>>

>> E.g. in src/std/math.d I wonder if it just shouldn't be done through

>> version (S390)      version = IBMZ_Any;

>> version (SystemZ)   version = IBMZ_Any;

>> and using later version (IBMZ_Any) instead of version (SystemZ).  Guess

>> in various other spots, except for those where structure sizes are needed.

>>

>> Robin, have you been testing with --disable-multilib or something similar?

>>

> 

> I built all compilers last night from config-list.mk, so I had a ready

> cross compiler available.  With the following patch, all compiles

> successfully with -fsyntax-only for both s390x-linux and s390-linux,

> though checking on native hardware would be preferred.


builds with the gcc-9 branch and trunk, natively and cross.
Robin Dapp April 29, 2019, 8:57 a.m. | #26
> Robin, have you been testing with --disable-multilib or something

> similar?


yes, I believe so... stupid mistake :(
Thanks for fixing it so quickly.
Iain Buclaw April 29, 2019, 9:39 a.m. | #27
On Mon, 29 Apr 2019 at 06:11, Matthias Klose <doko@ubuntu.com> wrote:
>

> On 27.04.19 14:08, Iain Buclaw wrote:

> > On Sat, 27 Apr 2019 at 12:24, Jakub Jelinek <jakub@redhat.com> wrote:

> >>

> >> On Sat, Apr 27, 2019 at 11:26:15AM +0200, Matthias Klose wrote:

> >>> On 15.03.19 16:49, Robin Dapp wrote:

> >>>> 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.

> >>>

> >>> this now fails on trunk and the gcc-9-branch with a multilib build:

> >>>

> >>>

> >>> /<<PKGBUILDDIR>>/src/libphobos/libdruntime/core/sys/posix/ucontext.d:769:9:

> >>> error: static assert  "unimpleme

> >>> nted"

> >>>   769 |         static assert(0, "unimplemented");

> >>>       |         ^

> >>> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> >>> make[10]: Leaving directory

> >>> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> >>> make[9]: *** [Makefile:473: all-recursive] Error 1

> >>> make[10]: *** [Makefile:2149: core/thread.lo] Error 1

> >>> make[10]: Leaving directory

> >>> '/<<PKGBUILDDIR>>/build/s390x-linux-gnu/32/libphobos/libdruntime'

> >>> make[9]: *** [Makefile:473: all-recursive] Error 1

> >>

> >> Ugh, can we disable D for GCC 9.1 on s390x then, on the trunk look through

> >> all files that only use version (SystemZ) and don't use version (S390) at

> >> least

> >> find -type f | xargs grep -l SystemZ | xargs grep -L S390

> >> ./src/std/uni.d

> >> ./src/std/math.d

> >> ./src/std/experimental/allocator/building_blocks/region.d

> >> ./libdruntime/gcc/sections/elf_shared.d

> >> ./libdruntime/core/sys/linux/link.d

> >> ./libdruntime/core/sys/posix/setjmp.d

> >> ./libdruntime/core/sys/posix/ucontext.d

> >> ./libdruntime/core/sys/posix/sys/stat.d

> >> and make sure it works also for s390 31-bit and finally backport to 9.2?

> >>

> >> E.g. in src/std/math.d I wonder if it just shouldn't be done through

> >> version (S390)      version = IBMZ_Any;

> >> version (SystemZ)   version = IBMZ_Any;

> >> and using later version (IBMZ_Any) instead of version (SystemZ).  Guess

> >> in various other spots, except for those where structure sizes are needed.

> >>

> >> Robin, have you been testing with --disable-multilib or something similar?

> >>

> >

> > I built all compilers last night from config-list.mk, so I had a ready

> > cross compiler available.  With the following patch, all compiles

> > successfully with -fsyntax-only for both s390x-linux and s390-linux,

> > though checking on native hardware would be preferred.

>

> builds with the gcc-9 branch and trunk, natively and cross.


Thanks, committed to branch.

-- 
Iain

Patch

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);