Hi,

This patch merges the D front-end implementation with upstream dmd
d0d4f02a0.

Removes the implementation of __traits(argTypes), which only supported
x86_64 targets.  The only use of this trait is an unused va_arg()
function, this has been removed as well.

Bootstrapped and regression tested on x86_64-linux-gnu, committed to
mainline.

Regards
Iain

---
gcc/d/ChangeLog:

2020-04-12  Iain Buclaw  <ibuc...@gdcproject.org>

        * Make-lang.in (D_FRONTEND_OBJS): Remove d/argtypes.o.
        * d-target.cc (Target::toArgTypes): New function.

libphobos/ChangeLog:

2020-04-12  Iain Buclaw  <ibuc...@gdcproject.org>

        * libdruntime/core/stdc/stdarg.d: Remove run-time va_list template.
---
 gcc/d/Make-lang.in                            |   1 -
 gcc/d/d-target.cc                             |  12 +
 gcc/d/dmd/MERGE                               |   2 +-
 gcc/d/dmd/argtypes.c                          | 484 ------------------
 gcc/d/dmd/dstruct.c                           |   4 +-
 gcc/d/dmd/expressionsem.c                     |   4 +-
 gcc/d/dmd/target.h                            |   2 +
 .../gdc.test/runnable/testargtypes.d          | 113 ----
 libphobos/libdruntime/core/stdc/stdarg.d      | 160 ------
 9 files changed, 19 insertions(+), 764 deletions(-)
 delete mode 100644 gcc/d/dmd/argtypes.c
 delete mode 100644 gcc/testsuite/gdc.test/runnable/testargtypes.d

diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 71dccad5a74..ac04d074aa5 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -59,7 +59,6 @@ D_FRONTEND_OBJS = \
        d/access.o \
        d/aliasthis.o \
        d/apply.o \
-       d/argtypes.o \
        d/arrayop.o \
        d/attrib.o \
        d/blockexit.o \
diff --git a/gcc/d/d-target.cc b/gcc/d/d-target.cc
index 7e11bd64abb..b2df2660579 100644
--- a/gcc/d/d-target.cc
+++ b/gcc/d/d-target.cc
@@ -410,3 +410,15 @@ Target::systemLinkage (void)
 {
   return LINKc;
 }
+
+/* Generate a TypeTuple of the equivalent types used to determine if a
+   function argument of the given type can be passed in registers.
+   The results of this are highly platform dependent, and intended
+   primarly for use in implementing va_arg() with RTTI.  */
+
+TypeTuple *
+Target::toArgTypes (Type *)
+{
+  /* Not implemented, however this is not currently used anywhere.  */
+  return NULL;
+}
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 7f0140708c6..374ec119ecf 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-3e10e2dd29e583f1d94d84de5e4bd858e0303669
+d0d4f02a0c43a95ff7aee2e296bab57ba7d06bf4
 
 The first line of this file holds the git revision number of the last
 merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/argtypes.c b/gcc/d/dmd/argtypes.c
deleted file mode 100644
index bed1d4020ab..00000000000
--- a/gcc/d/dmd/argtypes.c
+++ /dev/null
@@ -1,484 +0,0 @@
-
-/* Compiler implementation of the D programming language
- * Copyright (C) 2010-2019 by The D Language Foundation, All Rights Reserved
- * written by Walter Bright
- * http://www.digitalmars.com
- * Distributed under the Boost Software License, Version 1.0.
- * http://www.boost.org/LICENSE_1_0.txt
- * https://github.com/D-Programming-Language/dmd/blob/master/src/argtypes.c
- */
-
-#include "root/dsystem.h"
-#include "root/checkedint.h"
-
-#include "mars.h"
-#include "dsymbol.h"
-#include "mtype.h"
-#include "scope.h"
-#include "init.h"
-#include "expression.h"
-#include "attrib.h"
-#include "declaration.h"
-#include "template.h"
-#include "id.h"
-#include "enum.h"
-#include "import.h"
-#include "aggregate.h"
-#include "hdrgen.h"
-
-/****************************************************
- * This breaks a type down into 'simpler' types that can be passed to a 
function
- * in registers, and returned in registers.
- * It's highly platform dependent.
- * Params:
- *      t = type to break down
- * Returns:
- *      tuple of types, each element can be passed in a register.
- *      A tuple of zero length means the type cannot be passed/returned in 
registers.
- */
-
-TypeTuple *toArgTypes(Type *t)
-{
-    class ToArgTypes : public Visitor
-    {
-    public:
-        TypeTuple *result;
-
-        ToArgTypes()
-        {
-            result = NULL;
-        }
-
-        void visit(Type *)
-        {
-            // not valid for a parameter
-        }
-
-        void visit(TypeError *)
-        {
-            result = new TypeTuple(Type::terror);
-        }
-
-        void visit(TypeBasic *t)
-        {
-            Type *t1 = NULL;
-            Type *t2 = NULL;
-            switch (t->ty)
-            {
-                case Tvoid:
-                     return;
-
-                case Tbool:
-                case Tint8:
-                case Tuns8:
-                case Tint16:
-                case Tuns16:
-                case Tint32:
-                case Tuns32:
-                case Tfloat32:
-                case Tint64:
-                case Tuns64:
-                case Tint128:
-                case Tuns128:
-                case Tfloat64:
-                case Tfloat80:
-                    t1 = t;
-                    break;
-
-                case Timaginary32:
-                    t1 = Type::tfloat32;
-                    break;
-
-                case Timaginary64:
-                    t1 = Type::tfloat64;
-                    break;
-
-                case Timaginary80:
-                    t1 = Type::tfloat80;
-                    break;
-
-                case Tcomplex32:
-                    if (global.params.is64bit)
-                        t1 = Type::tfloat64;
-                    else
-                    {
-                        t1 = Type::tfloat64;
-                        t2 = Type::tfloat64;
-                    }
-                    break;
-
-                case Tcomplex64:
-                    t1 = Type::tfloat64;
-                    t2 = Type::tfloat64;
-                    break;
-
-                case Tcomplex80:
-                    t1 = Type::tfloat80;
-                    t2 = Type::tfloat80;
-                    break;
-
-                case Tchar:
-                    t1 = Type::tuns8;
-                    break;
-
-                case Twchar:
-                    t1 = Type::tuns16;
-                    break;
-
-                case Tdchar:
-                    t1 = Type::tuns32;
-                    break;
-
-                default:
-                    assert(0);
-            }
-
-            if (t1)
-            {
-                if (t2)
-                    result = new TypeTuple(t1, t2);
-                else
-                    result = new TypeTuple(t1);
-            }
-            else
-                result = new TypeTuple();
-        }
-
-        void visit(TypeVector *t)
-        {
-            result = new TypeTuple(t);
-        }
-
-        void visit(TypeSArray *t)
-        {
-            if (t->dim)
-            {
-                /* Should really be done as if it were a struct with dim 
members
-                 * of the array's elements.
-                 * I.e. int[2] should be done like struct S { int a; int b; }
-                 */
-                dinteger_t sz = t->dim->toInteger();
-                // T[1] should be passed like T
-                if (sz == 1)
-                {
-                    t->next->accept(this);
-                    return;
-                }
-            }
-            result = new TypeTuple();     // pass on the stack for efficiency
-        }
-
-        void visit(TypeAArray *)
-        {
-            result = new TypeTuple(Type::tvoidptr);
-        }
-
-        void visit(TypePointer *)
-        {
-            result = new TypeTuple(Type::tvoidptr);
-        }
-
-        /*************************************
-         * Convert a floating point type into the equivalent integral type.
-         */
-
-        static Type *mergeFloatToInt(Type *t)
-        {
-            switch (t->ty)
-            {
-                case Tfloat32:
-                case Timaginary32:
-                    t = Type::tint32;
-                    break;
-                case Tfloat64:
-                case Timaginary64:
-                case Tcomplex32:
-                    t = Type::tint64;
-                    break;
-                default:
-                    assert(0);
-            }
-            return t;
-        }
-
-        /*************************************
-         * This merges two types into an 8byte type.
-         * Params:
-         *      t1 = first type (can be null)
-         *      t2 = second type (can be null)
-         *      offset2 = offset of t2 from start of t1
-         * Returns:
-         *      type that encompasses both t1 and t2, null if cannot be done
-         */
-
-        static Type *argtypemerge(Type *t1, Type *t2, unsigned offset2)
-        {
-            //printf("argtypemerge(%s, %s, %d)\n", t1 ? t1->toChars() : "", t2 
? t2->toChars() : "", offset2);
-            if (!t1)
-            {   assert(!t2 || offset2 == 0);
-                return t2;
-            }
-            if (!t2)
-                return t1;
-
-            const d_uns64 sz1 = t1->size(Loc());
-            const d_uns64 sz2 = t2->size(Loc());
-            assert(sz1 != SIZE_INVALID && sz2 != SIZE_INVALID);
-
-            if (t1->ty != t2->ty &&
-                (t1->ty == Tfloat80 || t2->ty == Tfloat80))
-                return NULL;
-
-            // [float,float] => [cfloat]
-            if (t1->ty == Tfloat32 && t2->ty == Tfloat32 && offset2 == 4)
-                return Type::tfloat64;
-
-            // Merging floating and non-floating types produces the 
non-floating type
-            if (t1->isfloating())
-            {
-                if (!t2->isfloating())
-                    t1 = mergeFloatToInt(t1);
-            }
-            else if (t2->isfloating())
-                t2 = mergeFloatToInt(t2);
-
-            Type *t;
-
-            // Pick type with larger size
-            if (sz1 < sz2)
-                t = t2;
-            else
-                t = t1;
-
-            // If t2 does not lie within t1, need to increase the size of t to 
enclose both
-            assert(sz2 < UINT64_MAX - UINT32_MAX);
-            if (offset2 && sz1 < offset2 + sz2)
-            {
-                switch (offset2 + sz2)
-                {
-                    case 2:
-                        t = Type::tint16;
-                        break;
-                    case 3:
-                    case 4:
-                        t = Type::tint32;
-                        break;
-                    default:
-                        t = Type::tint64;
-                        break;
-                }
-            }
-            return t;
-        }
-
-        void visit(TypeDArray *)
-        {
-            /* Should be done as if it were:
-             * struct S { size_t length; void* ptr; }
-             */
-            if (global.params.is64bit && !global.params.isLP64)
-            {
-                // For AMD64 ILP32 ABI, D arrays fit into a single integer 
register.
-                unsigned offset = (unsigned)Type::tsize_t->size(Loc());
-                Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
-                if (t)
-                {
-                    result = new TypeTuple(t);
-                    return;
-                }
-            }
-            result = new TypeTuple(Type::tsize_t, Type::tvoidptr);
-        }
-
-        void visit(TypeDelegate *)
-        {
-            /* Should be done as if it were:
-             * struct S { size_t length; void* ptr; }
-             */
-            if (global.params.is64bit && !global.params.isLP64)
-            {
-                // For AMD64 ILP32 ABI, delegates fit into a single integer 
register.
-                unsigned offset = (unsigned)Type::tsize_t->size(Loc());
-                Type *t = argtypemerge(Type::tsize_t, Type::tvoidptr, offset);
-                if (t)
-                {
-                    result = new TypeTuple(t);
-                    return;
-                }
-            }
-            result = new TypeTuple(Type::tvoidptr, Type::tvoidptr);
-        }
-
-        void visit(TypeStruct *t)
-        {
-            //printf("TypeStruct::toArgTypes() %s\n", t->toChars());
-            if (!t->sym->isPOD() || t->sym->fields.dim == 0)
-            {
-            Lmemory:
-                //printf("\ttoArgTypes() %s => [ ]\n", t->toChars());
-                result = new TypeTuple();         // pass on the stack
-                return;
-            }
-            Type *t1 = NULL;
-            Type *t2 = NULL;
-            const d_uns64 sz = t->size(Loc());
-            assert(sz < 0xFFFFFFFF);
-            switch ((unsigned)sz)
-            {
-                case 1:
-                    t1 = Type::tint8;
-                    break;
-                case 2:
-                    t1 = Type::tint16;
-                    break;
-                case 3:
-                    if (!global.params.is64bit)
-                        goto Lmemory;
-                    /* fall through */
-                case 4:
-                    t1 = Type::tint32;
-                    break;
-                case 5:
-                case 6:
-                case 7:
-                    if (!global.params.is64bit)
-                        goto Lmemory;
-                    /* fall through */
-                case 8:
-                    t1 = Type::tint64;
-                    break;
-                case 16:
-                    t1 = NULL;                   // could be a TypeVector
-                    break;
-                case 9:
-                case 10:
-                case 11:
-                case 12:
-                case 13:
-                case 14:
-                case 15:
-                    if (!global.params.is64bit)
-                        goto Lmemory;
-                    t1 = NULL;
-                    break;
-                default:
-                    goto Lmemory;
-            }
-            if (global.params.is64bit && t->sym->fields.dim)
-            {
-                t1 = NULL;
-                for (size_t i = 0; i < t->sym->fields.dim; i++)
-                {
-                    VarDeclaration *f = t->sym->fields[i];
-                    //printf("  [%d] %s f->type = %s\n", (int)i, f->toChars(), 
f->type->toChars());
-
-                    TypeTuple *tup = toArgTypes(f->type);
-                    if (!tup)
-                        goto Lmemory;
-                    size_t dim = tup->arguments->dim;
-                    Type *ft1 = NULL;
-                    Type *ft2 = NULL;
-                    switch (dim)
-                    {
-                        case 2:
-                            ft1 = (*tup->arguments)[0]->type;
-                            ft2 = (*tup->arguments)[1]->type;
-                            break;
-                        case 1:
-                            if (f->offset < 8)
-                                ft1 = (*tup->arguments)[0]->type;
-                            else
-                                ft2 = (*tup->arguments)[0]->type;
-                            break;
-                        default:
-                            goto Lmemory;
-                    }
-
-                    if (f->offset & 7)
-                    {
-                        // Misaligned fields goto Lmemory
-                        unsigned alignsz = f->type->alignsize();
-                        if (f->offset & (alignsz - 1))
-                            goto Lmemory;
-
-                        // Fields that overlap the 8byte boundary goto Lmemory
-                        const d_uns64 fieldsz = f->type->size(Loc());
-                        assert(fieldsz != SIZE_INVALID && fieldsz < UINT64_MAX 
- UINT32_MAX);
-                        if (f->offset < 8 && (f->offset + fieldsz) > 8)
-                            goto Lmemory;
-                    }
-
-                    // First field in 8byte must be at start of 8byte
-                    assert(t1 || f->offset == 0);
-                    //printf("ft1 = %s\n", ft1 ? ft1->toChars() : "null");
-                    //printf("ft2 = %s\n", ft2 ? ft2->toChars() : "null");
-                    if (ft1)
-                    {
-                        t1 = argtypemerge(t1, ft1, f->offset);
-                        if (!t1)
-                            goto Lmemory;
-                    }
-
-                    if (ft2)
-                    {
-                        unsigned off2 = f->offset;
-                        if (ft1)
-                            off2 = 8;
-                        if (!t2 && off2 != 8)
-                            goto Lmemory;
-                        assert(t2 || off2 == 8);
-                        t2 = argtypemerge(t2, ft2, off2 - 8);
-                        if (!t2)
-                            goto Lmemory;
-                    }
-                }
-
-                if (t2)
-                {
-                    if (t1->isfloating() && t2->isfloating())
-                    {
-                        if ((t1->ty == Tfloat32 || t1->ty == Tfloat64) &&
-                            (t2->ty == Tfloat32 || t2->ty == Tfloat64))
-                            ;
-                        else
-                            goto Lmemory;
-                    }
-                    else if (t1->isfloating())
-                        goto Lmemory;
-                    else if (t2->isfloating())
-                        goto Lmemory;
-                    else
-                    {
-                    }
-                }
-            }
-
-            //printf("\ttoArgTypes() %s => [%s,%s]\n", t->toChars(), t1 ? 
t1->toChars() : "", t2 ? t2->toChars() : "");
-
-            if (t1)
-            {
-                //if (t1) printf("test1: %s => %s\n", toChars(), 
t1->toChars());
-                if (t2)
-                    result = new TypeTuple(t1, t2);
-                else
-                    result = new TypeTuple(t1);
-            }
-            else
-                goto Lmemory;
-        }
-
-        void visit(TypeEnum *t)
-        {
-            t->toBasetype()->accept(this);
-        }
-
-        void visit(TypeClass *)
-        {
-            result = new TypeTuple(Type::tvoidptr);
-        }
-    };
-
-    ToArgTypes v;
-    t->accept(&v);
-    return v.result;
-}
diff --git a/gcc/d/dmd/dstruct.c b/gcc/d/dmd/dstruct.c
index 22da0a3be3d..865d18a2196 100644
--- a/gcc/d/dmd/dstruct.c
+++ b/gcc/d/dmd/dstruct.c
@@ -22,9 +22,9 @@
 #include "statement.h"
 #include "template.h"
 #include "tokens.h"
+#include "target.h"
 
 Type *getTypeInfoType(Loc loc, Type *t, Scope *sc);
-TypeTuple *toArgTypes(Type *t);
 void unSpeculative(Scope *sc, RootObject *o);
 bool MODimplicitConv(MOD modfrom, MOD modto);
 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
@@ -1303,8 +1303,8 @@ void StructDeclaration::finalizeSize()
         }
     }
 
-    TypeTuple *tt = toArgTypes(type);
-    size_t dim = tt->arguments->dim;
+    TypeTuple *tt = Target::toArgTypes(type);
+    size_t dim = tt ? tt->arguments->dim : 0;
     if (dim >= 1)
     {
         assert(dim <= 2);
diff --git a/gcc/d/dmd/expressionsem.c b/gcc/d/dmd/expressionsem.c
index fed36cf9242..629768aaf06 100644
--- a/gcc/d/dmd/expressionsem.c
+++ b/gcc/d/dmd/expressionsem.c
@@ -37,7 +37,6 @@
 bool typeMerge(Scope *sc, TOK op, Type **pt, Expression **pe1, Expression 
**pe2);
 bool isArrayOpValid(Expression *e);
 Expression *expandVar(int result, VarDeclaration *v);
-TypeTuple *toArgTypes(Type *t);
 bool checkAssignEscape(Scope *sc, Expression *e, bool gag);
 bool checkParamArgumentEscape(Scope *sc, FuncDeclaration *fdc, Identifier 
*par, Expression *arg, bool gag);
 bool checkAccess(AggregateDeclaration *ad, Loc loc, Scope *sc, Dsymbol 
*smember);
@@ -2074,7 +2073,7 @@ public:
                      * The results of this are highly platform dependent, and 
intended
                      * primarly for use in implementing va_arg().
                      */
-                    tded = toArgTypes(e->targ);
+                    tded = Target::toArgTypes(e->targ);
                     if (!tded)
                         goto Lno;           // not valid for a parameter
                     break;
diff --git a/gcc/d/dmd/target.h b/gcc/d/dmd/target.h
index 1729bc33ffa..51e85ff7ca9 100644
--- a/gcc/d/dmd/target.h
+++ b/gcc/d/dmd/target.h
@@ -21,6 +21,7 @@ class Dsymbol;
 class Expression;
 class Parameter;
 class Type;
+class TypeTuple;
 struct OutBuffer;
 
 struct Target
@@ -73,4 +74,5 @@ struct Target
     static Type *cppParameterType(Parameter *p);
     static bool cppFundamentalType(const Type *t, bool& isFundamental);
     static LINK systemLinkage();
+    static TypeTuple *toArgTypes(Type *t);
 };
diff --git a/gcc/testsuite/gdc.test/runnable/testargtypes.d 
b/gcc/testsuite/gdc.test/runnable/testargtypes.d
deleted file mode 100644
index 343a1c80e14..00000000000
--- a/gcc/testsuite/gdc.test/runnable/testargtypes.d
+++ /dev/null
@@ -1,113 +0,0 @@
-
-void chkArgTypes(S, V...)()
-{
-    pragma(msg, S);
-    static if (is(S U == __argTypes))
-    {
-        foreach (T; U) { pragma(msg, T); }
-        static assert(U.length == V.length);
-        foreach (i, T; U)
-            static assert(is(V[i] == T));
-    }
-    else
-        static assert(0);
-}
-
-void chkSingle(T,U)()
-{
-    struct S { T a; }
-    chkArgTypes!(S, U)();
-}
-
-void chkIdentity(T)()
-{
-    chkSingle!(T,T)();
-}
-
-void chkPair(T,U,V)()
-{
-    struct S { T a; U b; }
-    chkArgTypes!(S, V)();
-}
-
-version (X86_64)
-{
-    int main()
-    {
-        chkIdentity!byte();
-        chkIdentity!ubyte();
-        chkIdentity!short();
-        chkIdentity!ushort();
-        chkIdentity!int();
-        chkIdentity!uint();
-        chkIdentity!long();
-        chkIdentity!ulong();
-        chkSingle!(char,ubyte)();
-        chkSingle!(wchar,ushort)();
-        chkSingle!(dchar,uint)();
-
-        chkIdentity!float();
-        chkIdentity!double();
-        chkIdentity!real();
-
-        chkIdentity!(void*)();
-
-        chkIdentity!(__vector(byte[16]))();
-        chkIdentity!(__vector(ubyte[16]))();
-        chkIdentity!(__vector(short[8]))();
-        chkIdentity!(__vector(ushort[8]))();
-        chkIdentity!(__vector(int[4]))();
-        chkIdentity!(__vector(uint[4]))();
-        chkIdentity!(__vector(long[2]))();
-        chkIdentity!(__vector(ulong[2]))();
-
-        chkIdentity!(__vector(float[4]))();
-        chkIdentity!(__vector(double[2]))();
-
-        chkPair!(byte,byte,short);
-        chkPair!(ubyte,ubyte,short);
-        chkPair!(short,short,int);
-        chkPair!(int,int,long);
-
-        chkPair!(byte,short,int);
-        chkPair!(short,byte,int);
-
-        chkPair!(int,float,long);
-        chkPair!(float,int,long);
-        chkPair!(byte,float,long);
-        chkPair!(float,short,long);
-
-        //struct S1 { long a; long b; }
-        //chkArgTypes!(S1, long, long)();
-
-        struct S2 { union { long a; double d; }}
-        chkArgTypes!(S2, long)();
-
-        struct S3 { union { double d; long a; }}
-        chkArgTypes!(S3, long)();
-
-        struct S4 { int a,b,c,d,e; }
-        chkArgTypes!(S4)();
-
-        struct S5 { align(1): char a; int b; }
-        chkArgTypes!(S5)();
-
-        struct S6 { align(1): int a; void* b; }
-        chkArgTypes!(S5)();
-
-        struct S7 { union { void* p; real r; }}
-        chkArgTypes!(S7)();
-
-        struct S8 { union { real r; void* p; }}
-        chkArgTypes!(S8)();
-
-        return 0;
-    }
-}
-else
-{
-    int main()
-    {
-        return 0;
-    }
-}
diff --git a/libphobos/libdruntime/core/stdc/stdarg.d 
b/libphobos/libdruntime/core/stdc/stdarg.d
index 613138f968e..586fe20d991 100644
--- a/libphobos/libdruntime/core/stdc/stdarg.d
+++ b/libphobos/libdruntime/core/stdc/stdarg.d
@@ -50,166 +50,6 @@ version (GNU)
     void va_arg(T)(ref va_list ap, ref T parmn);
 
 
-    /*************
-     * Retrieve and store through parmn the next value that is of TypeInfo ti.
-     * Used when the static type is not known.
-     */
-    version (X86)
-    {
-        ///
-        void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
-        {
-            auto p = ap;
-            auto tsize = ti.tsize;
-            ap = cast(va_list)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & 
~(size_t.sizeof - 1)));
-            parmn[0..tsize] = p[0..tsize];
-        }
-    }
-    else version (X86_64)
-    {
-        /// Layout of this struct must match __builtin_va_list for C ABI 
compatibility
-        struct __va_list
-        {
-            uint offset_regs = 6 * 8;            // no regs
-            uint offset_fpregs = 6 * 8 + 8 * 16; // no fp regs
-            void* stack_args;
-            void* reg_args;
-        }
-
-        ///
-        void va_arg()(ref va_list apx, TypeInfo ti, void* parmn)
-        {
-            __va_list* ap = cast(__va_list*)apx;
-            TypeInfo arg1, arg2;
-            if (!ti.argTypes(arg1, arg2))
-            {
-                bool inXMMregister(TypeInfo arg) pure nothrow @safe
-                {
-                    return (arg.flags & 2) != 0;
-                }
-
-                TypeInfo_Vector v1 = arg1 ? cast(TypeInfo_Vector)arg1 : null;
-                if (arg1 && (arg1.tsize() <= 8 || v1))
-                {   // Arg is passed in one register
-                    auto tsize = arg1.tsize();
-                    void* p;
-                    bool stack = false;
-                    auto offset_fpregs_save = ap.offset_fpregs;
-                    auto offset_regs_save = ap.offset_regs;
-                L1:
-                    if (inXMMregister(arg1) || v1)
-                    {   // Passed in XMM register
-                        if (ap.offset_fpregs < (6 * 8 + 16 * 8) && !stack)
-                        {
-                            p = ap.reg_args + ap.offset_fpregs;
-                            ap.offset_fpregs += 16;
-                        }
-                        else
-                        {
-                            p = ap.stack_args;
-                            ap.stack_args += (tsize + size_t.sizeof - 1) & 
~(size_t.sizeof - 1);
-                            stack = true;
-                        }
-                    }
-                    else
-                    {   // Passed in regular register
-                        if (ap.offset_regs < 6 * 8 && !stack)
-                        {
-                            p = ap.reg_args + ap.offset_regs;
-                            ap.offset_regs += 8;
-                        }
-                        else
-                        {
-                            p = ap.stack_args;
-                            ap.stack_args += 8;
-                            stack = true;
-                        }
-                    }
-                    parmn[0..tsize] = p[0..tsize];
-
-                    if (arg2)
-                    {
-                        if (inXMMregister(arg2))
-                        {   // Passed in XMM register
-                            if (ap.offset_fpregs < (6 * 8 + 16 * 8) && !stack)
-                            {
-                                p = ap.reg_args + ap.offset_fpregs;
-                                ap.offset_fpregs += 16;
-                            }
-                            else
-                            {
-                                if (!stack)
-                                {   // arg1 is really on the stack, so rewind 
and redo
-                                    ap.offset_fpregs = offset_fpregs_save;
-                                    ap.offset_regs = offset_regs_save;
-                                    stack = true;
-                                    goto L1;
-                                }
-                                p = ap.stack_args;
-                                ap.stack_args += (arg2.tsize() + size_t.sizeof 
- 1) & ~(size_t.sizeof - 1);
-                            }
-                        }
-                        else
-                        {   // Passed in regular register
-                            if (ap.offset_regs < 6 * 8 && !stack)
-                            {
-                                p = ap.reg_args + ap.offset_regs;
-                                ap.offset_regs += 8;
-                            }
-                            else
-                            {
-                                if (!stack)
-                                {   // arg1 is really on the stack, so rewind 
and redo
-                                    ap.offset_fpregs = offset_fpregs_save;
-                                    ap.offset_regs = offset_regs_save;
-                                    stack = true;
-                                    goto L1;
-                                }
-                                p = ap.stack_args;
-                                ap.stack_args += 8;
-                            }
-                        }
-                        auto sz = ti.tsize() - 8;
-                        (parmn + 8)[0..sz] = p[0..sz];
-                    }
-                }
-                else
-                {   // Always passed in memory
-                    // The arg may have more strict alignment than the stack
-                    auto talign = ti.talign();
-                    auto tsize = ti.tsize();
-                    auto p = cast(void*)((cast(size_t)ap.stack_args + talign - 
1) & ~(talign - 1));
-                    ap.stack_args = cast(void*)(cast(size_t)p + ((tsize + 
size_t.sizeof - 1) & ~(size_t.sizeof - 1)));
-                    parmn[0..tsize] = p[0..tsize];
-                }
-            }
-            else
-            {
-                assert(false, "not a valid argument type for va_arg");
-            }
-        }
-    }
-    else version (ARM)
-    {
-        ///
-        void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
-        {
-            auto p = *cast(void**) &ap;
-            auto tsize = ti.tsize();
-            *cast(void**) &ap += ( tsize + size_t.sizeof - 1 ) & ~( 
size_t.sizeof - 1 );
-            parmn[0..tsize] = p[0..tsize];
-        }
-    }
-    else
-    {
-        ///
-        void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
-        {
-            static assert(false, "Unsupported platform");
-        }
-    }
-
-
     /***********************
      * End use of ap.
      */
-- 
2.20.1

Reply via email to