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 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 (RISCV32) version = RISCV_Any; 32 version (RISCV64) version = RISCV_Any; 33 34 version (ARM_Any) 35 { 36 // Darwin uses a simpler varargs implementation 37 version (OSX) {} 38 else version (iOS) {} 39 else version (TVOS) {} 40 else version (WatchOS) {} 41 else: 42 43 version (ARM) version = AAPCS32; 44 version (AArch64) version = AAPCS64; 45 } 46 47 48 /// 49 alias va_arg = core.stdc.stdarg.va_arg; 50 51 52 /** 53 * Retrieve and store through parmn the next value that is of TypeInfo ti. 54 * Used when the static type is not known. 55 */ 56 void va_arg()(ref va_list ap, TypeInfo ti, void* parmn) 57 { 58 version (X86) 59 { 60 // Wait until everyone updates to get TypeInfo.talign 61 //auto talign = ti.talign; 62 //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); 63 auto p = ap; 64 auto tsize = ti.tsize; 65 ap = cast(va_list) (p + tsize.alignUp); 66 parmn[0..tsize] = p[0..tsize]; 67 } 68 else version (Win64) 69 { 70 version (LDC) enum isLDC = true; 71 else enum isLDC = false; 72 73 // Wait until everyone updates to get TypeInfo.talign 74 //auto talign = ti.talign; 75 //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); 76 auto p = ap; 77 auto tsize = ti.tsize; 78 void* q; 79 if (isLDC && tsize == 16 && cast(TypeInfo_Array) ti) 80 { 81 q = p; 82 ap = cast(va_list) (p + tsize); 83 } 84 else 85 { 86 q = (tsize > size_t.sizeof || (tsize & (tsize - 1)) != 0) ? *cast(void**) p : p; 87 ap = cast(va_list) (p + size_t.sizeof); 88 } 89 parmn[0..tsize] = q[0..tsize]; 90 } 91 else version (X86_64) 92 { 93 static import core.internal.vararg.sysv_x64; 94 core.internal.vararg.sysv_x64.va_arg(ap, ti, parmn); 95 } 96 else version (AAPCS32) 97 { 98 const tsize = ti.tsize; 99 if (ti.talign >= 8) 100 ap.__ap = ap.__ap.alignUp!8; 101 auto p = ap.__ap; 102 version (BigEndian) 103 p = adjustForBigEndian(p, tsize); 104 ap.__ap += tsize.alignUp; 105 parmn[0..tsize] = p[0..tsize]; 106 } 107 else version (AAPCS64) 108 { 109 static import core.internal.vararg.aarch64; 110 core.internal.vararg.aarch64.va_arg(ap, ti, parmn); 111 } 112 else version (ARM_Any) 113 { 114 const tsize = ti.tsize; 115 auto p = cast(void*) ap; 116 version (BigEndian) 117 p = adjustForBigEndian(p, tsize); 118 ap += tsize.alignUp; 119 parmn[0..tsize] = p[0..tsize]; 120 } 121 else version (PPC_Any) 122 { 123 if (ti.talign >= 8) 124 ap = ap.alignUp!8; 125 const tsize = ti.tsize; 126 auto p = cast(void*) ap; 127 version (BigEndian) 128 p = adjustForBigEndian(p, tsize); 129 ap += tsize.alignUp; 130 parmn[0..tsize] = p[0..tsize]; 131 } 132 else version (LoongArch64) 133 { 134 const tsize = ti.tsize; 135 auto p = cast(void*) ap; 136 ap += tsize.alignUp; 137 parmn[0..tsize] = p[0..tsize]; 138 } 139 else version (MIPS_Any) 140 { 141 const tsize = ti.tsize; 142 auto p = cast(void*) ap; 143 version (BigEndian) 144 p = adjustForBigEndian(p, tsize); 145 ap += tsize.alignUp; 146 parmn[0..tsize] = p[0..tsize]; 147 } 148 else version (RISCV_Any) 149 { 150 const tsize = ti.tsize; 151 void* p; 152 if (tsize > (size_t.sizeof << 1)) 153 p = *cast(void**) ap; 154 else 155 { 156 if (tsize == (size_t.sizeof << 1)) 157 ap = ap.alignUp!(size_t.sizeof << 1); 158 p = cast(void*) ap; 159 } 160 ap += tsize.alignUp; 161 parmn[0..tsize] = p[0..tsize]; 162 } 163 else 164 static assert(0, "Unsupported platform"); 165 }