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 */ 17module core.vararg; 18 19public import core.stdc.stdarg; 20 21 22version (GNU) { /* TypeInfo-based va_arg overload unsupported */ } 23else: 24 25version (ARM) version = ARM_Any; 26version (AArch64) version = ARM_Any; 27version (MIPS32) version = MIPS_Any; 28version (MIPS64) version = MIPS_Any; 29version (PPC) version = PPC_Any; 30version (PPC64) version = PPC_Any; 31 32version (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/// 47alias 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 */ 54void 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