From: Iain Buclaw Date: Mon, 13 Apr 2020 09:25:26 +0000 (+0200) Subject: d: Merge update dmd 799066f49 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a1ccbae63cdf25b8ff66da18ed0d081cb9411ccf;p=gcc.git d: Merge update dmd 799066f49 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. Reviewed-on: https://github.com/dlang/dmd/pull/11022 gcc/d/ChangeLog: 2020-04-13 Iain Buclaw * Make-lang.in (D_FRONTEND_OBJS): Remove d/argtypes.o. * d-target.cc (Target::toArgTypes): New function. libphobos/ChangeLog: 2020-04-13 Iain Buclaw * libdruntime/core/stdc/stdarg.d: Remove run-time va_list template. --- diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog index 5f7e9672866..6544b3d324e 100644 --- a/gcc/d/ChangeLog +++ b/gcc/d/ChangeLog @@ -1,3 +1,8 @@ +2020-04-13 Iain Buclaw + + * Make-lang.in (D_FRONTEND_OBJS): Remove d/argtypes.o. + * d-target.cc (Target::toArgTypes): New function. + 2020-04-10 Iain Buclaw * d-spec.cc (LIBDRUNTIME): Remove. 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..dc9fb1b8d97 100644 --- a/gcc/d/dmd/MERGE +++ b/gcc/d/dmd/MERGE @@ -1,4 +1,4 @@ -3e10e2dd29e583f1d94d84de5e4bd858e0303669 +799066f498aebcfa420df284cac1f204b1f953a8 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..10771c95a07 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/ChangeLog b/libphobos/ChangeLog index 653f48115bd..e6eec480b1f 100644 --- a/libphobos/ChangeLog +++ b/libphobos/ChangeLog @@ -1,3 +1,7 @@ +2020-04-13 Iain Buclaw + + * libdruntime/core/stdc/stdarg.d: Remove run-time va_list template. + 2020-04-10 Iain Buclaw * d_rules.am (libdgruntime_la_LINK): Move to libdruntime/Makefile.am. 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**) ≈ - 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. */