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