1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/**
* The vararg module is intended to facilitate vararg manipulation in D.
* It should be interface compatible with the C module "stdarg," and the
* two modules may share a common implementation if possible (as is done
* here).
* Copyright: Copyright Digital Mars 2000 - 2009.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Walter Bright, Hauke Duden
* Source: $(DRUNTIMESRC core/_vararg.d)
*/
/* Copyright Digital Mars 2000 - 2009.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
module core.vararg;
public import core.stdc.stdarg;
version (GNU) { /* TypeInfo-based va_arg overload unsupported */ }
else:
version (ARM) version = ARM_Any;
version (AArch64) version = ARM_Any;
version (MIPS32) version = MIPS_Any;
version (MIPS64) version = MIPS_Any;
version (PPC) version = PPC_Any;
version (PPC64) version = PPC_Any;
version (ARM_Any)
{
// Darwin uses a simpler varargs implementation
version (OSX) {}
else version (iOS) {}
else version (TVOS) {}
else version (WatchOS) {}
else:
version (ARM) version = AAPCS32;
version (AArch64) version = AAPCS64;
}
///
alias va_arg = core.stdc.stdarg.va_arg;
/**
* Retrieve and store through parmn the next value that is of TypeInfo ti.
* Used when the static type is not known.
*/
void va_arg()(ref va_list ap, TypeInfo ti, void* parmn)
{
version (X86)
{
// Wait until everyone updates to get TypeInfo.talign
//auto talign = ti.talign;
//auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1);
auto p = ap;
auto tsize = ti.tsize;
ap = cast(va_list) (p + tsize.alignUp);
parmn[0..tsize] = p[0..tsize];
}
else version (Win64)
{
version (LDC) enum isLDC = true;
else enum isLDC = false;
// Wait until everyone updates to get TypeInfo.talign
//auto talign = ti.talign;
//auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1);
auto p = ap;
auto tsize = ti.tsize;
void* q;
if (isLDC && tsize == 16 && cast(TypeInfo_Array) ti)
{
q = p;
ap = cast(va_list) (p + tsize);
}
else
{
q = (tsize > size_t.sizeof || (tsize & (tsize - 1)) != 0) ? *cast(void**) p : p;
ap = cast(va_list) (p + size_t.sizeof);
}
parmn[0..tsize] = q[0..tsize];
}
else version (X86_64)
{
static import core.internal.vararg.sysv_x64;
core.internal.vararg.sysv_x64.va_arg(ap, ti, parmn);
}
else version (AAPCS32)
{
const tsize = ti.tsize;
if (ti.talign >= 8)
ap.__ap = ap.__ap.alignUp!8;
auto p = ap.__ap;
version (BigEndian)
p = adjustForBigEndian(p, tsize);
ap.__ap += tsize.alignUp;
parmn[0..tsize] = p[0..tsize];
}
else version (AAPCS64)
{
static import core.internal.vararg.aarch64;
core.internal.vararg.aarch64.va_arg(ap, ti, parmn);
}
else version (ARM_Any)
{
const tsize = ti.tsize;
auto p = cast(void*) ap;
version (BigEndian)
p = adjustForBigEndian(p, tsize);
ap += tsize.alignUp;
parmn[0..tsize] = p[0..tsize];
}
else version (PPC_Any)
{
if (ti.talign >= 8)
ap = ap.alignUp!8;
const tsize = ti.tsize;
auto p = cast(void*) ap;
version (BigEndian)
p = adjustForBigEndian(p, tsize);
ap += tsize.alignUp;
parmn[0..tsize] = p[0..tsize];
}
else version (MIPS_Any)
{
const tsize = ti.tsize;
auto p = cast(void*) ap;
version (BigEndian)
p = adjustForBigEndian(p, tsize);
ap += tsize.alignUp;
parmn[0..tsize] = p[0..tsize];
}
else
static assert(0, "Unsupported platform");
}
|