Ticket #2038: tango-dmd64.patch
File tango-dmd64.patch, 27.2 kB (added by Marenz, 13 years ago) |
---|
more work on 64bit dmd |
-
object.di
old new 131 131 PointerMap pointermap(); 132 132 /// offsets of the various elements 133 133 OffsetTypeInfo[] offTi(); 134 135 /** Return internal info on arguments fitting into 8byte. 136 * See X86-64 ABI 3.2.3 137 */ 138 version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2); 134 139 } 135 140 136 141 class TypeInfo_Typedef : TypeInfo -
tango/core/rt/gc/basic/gcx.d
old new 2344 2344 } 2345 2345 else 2346 2346 { 2347 asm2347 version (D_InlineAsm_X86) 2348 2348 { 2349 pushad ; 2350 mov sp[EBP],ESP ; 2349 asm 2350 { 2351 pushad ; 2352 mov sp[EBP],ESP ; 2353 } 2351 2354 } 2355 else version (D_InlineAsm_X86_64) 2356 { 2357 asm 2358 { 2359 push RAX ; 2360 push RBX ; 2361 push RCX ; 2362 push RDX ; 2363 push RSI ; 2364 push RDI ; 2365 push RBP ; 2366 push R8 ; 2367 push R9 ; 2368 push R10 ; 2369 push R11 ; 2370 push R12 ; 2371 push R13 ; 2372 push R14 ; 2373 push R15 ; 2374 push EAX ; // 16 byte align the stack 2375 } 2352 2376 } 2377 else 2378 { 2379 static assert( false, "Architecture not supported." ); 2380 } 2381 } 2353 2382 result = fullcollect(sp); 2354 2383 version (GNU) 2355 2384 { … … 2519 2548 for (n = 0; n < npools; n++) 2520 2549 { size_t pn; 2521 2550 size_t ncommitted; 2522 uint* bbase;2523 2551 2524 2552 pool = pooltable[n]; 2525 bbase = pool.mark.base();2553 auto bbase = pool.mark.base(); 2526 2554 ncommitted = pool.ncommitted; 2527 2555 for (pn = 0; pn < ncommitted; pn++, bbase += PAGESIZE / (32 * 16)) 2528 2556 { -
tango/core/rt/gc/basic/gcbits.d
old new 50 50 51 51 struct GCBits 52 52 { 53 const int BITS_PER_WORD = 32; 54 const int BITS_SHIFT = 5; 55 const int BITS_MASK = 31; 53 alias size_t wordtype; 56 54 57 uint* data = null; 55 const BITS_PER_WORD = (wordtype.sizeof * 8); 56 const BITS_SHIFT = (wordtype.sizeof == 8 ? 6 : 5); 57 const BITS_MASK = (BITS_PER_WORD - 1); 58 const BITS_1 = cast(wordtype)1; 59 60 wordtype* data = null; 58 61 size_t nwords = 0; // allocated words in data[] excluding sentinals 59 62 size_t nbits = 0; // number of bits in data[] excluding sentinals 60 63 … … 79 82 { 80 83 this.nbits = nbits; 81 84 nwords = (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT; 82 data = cast( uint*)calloc(nwords + 2, uint.sizeof);85 data = cast(wordtype*)calloc(nwords + 2, wordtype.sizeof); 83 86 if (!data) 84 87 onOutOfMemoryError(); 85 88 } 86 89 87 uinttest(size_t i)90 wordtype test(size_t i) 88 91 in 89 92 { 90 93 assert(i < nbits); … … 92 95 body 93 96 { 94 97 //return (cast(bit *)(data + 1))[i]; 95 return data[1 + (i >> BITS_SHIFT)] & ( 1 << (i & BITS_MASK));98 return data[1 + (i >> BITS_SHIFT)] & (BITS_1 << (i & BITS_MASK)); 96 99 } 97 100 98 101 void set(size_t i) … … 103 106 body 104 107 { 105 108 //(cast(bit *)(data + 1))[i] = 1; 106 data[1 + (i >> BITS_SHIFT)] |= ( 1 << (i & BITS_MASK));109 data[1 + (i >> BITS_SHIFT)] |= (BITS_1 << (i & BITS_MASK)); 107 110 } 108 111 109 112 void clear(size_t i) … … 114 117 body 115 118 { 116 119 //(cast(bit *)(data + 1))[i] = 0; 117 data[1 + (i >> BITS_SHIFT)] &= ~( 1 << (i & BITS_MASK));120 data[1 + (i >> BITS_SHIFT)] &= ~(BITS_1 << (i & BITS_MASK)); 118 121 } 119 122 120 uinttestClear(size_t i)123 wordtype testClear(size_t i) 121 124 { 122 125 version (bitops) 123 126 { … … 136 139 } 137 140 } 138 141 else 139 { uintresult;142 { wordtype result; 140 143 141 144 //result = (cast(bit *)(data + 1))[i]; 142 145 //(cast(bit *)(data + 1))[i] = 0; 143 146 144 uint* p = &data[1 + (i >> BITS_SHIFT)];145 uint mask = (1 << (i & BITS_MASK));147 wordtype* p = &data[1 + (i >> BITS_SHIFT)]; 148 wordtype mask = (BITS_1 << (i & BITS_MASK)); 146 149 result = *p & mask; 147 150 *p &= ~mask; 148 151 return result; … … 188 191 for (;d1!=dEnd;++d1) 189 192 *d1=0u; 190 193 } else { 191 memset(data + 1, 0, nwords * uint.sizeof);194 memset(data + 1, 0, nwords * wordtype.sizeof); 192 195 } 193 196 } 194 197 … … 200 203 body 201 204 { 202 205 version(MEMCPY_NON_SIG_SAFE) { 203 uint* d1=data+1,d2=f.data+1,dEnd=d1+nwords;206 wordtype * d1=data+1,d2=f.data+1,dEnd=d1+nwords; 204 207 for (;d1!=dEnd;++d1,++d2) 205 208 *d1=*d2; 206 209 } else { 207 memcpy(data + 1, f.data + 1, nwords * uint.sizeof);210 memcpy(data + 1, f.data + 1, nwords * wordtype.sizeof); 208 211 } 209 212 } 210 213 211 uint* base()214 wordtype* base() 212 215 in 213 216 { 214 217 assert(data); -
tango/core/rt/compiler/dmd/rt/lifetime.d
old new 303 303 if (ndims == 0) 304 304 result = 0; 305 305 else 306 { va_list q;307 va_ start!(int)(q, ndims);306 { 307 va_list q; 308 308 309 version(X86) 310 va_start(q, ndims); 311 else version(X86_64) 312 va_start(q, __va_argsave); 313 else 314 static assert(false, "platform not supported"); 315 309 316 void[] foo(TypeInfo ti, size_t* pdim, int ndims) 310 317 { 311 318 size_t dim = *pdim; … … 358 365 else 359 366 { 360 367 va_list q; 361 va_start!(int)(q, ndims);362 368 369 version(X86) 370 va_start(q, ndims); 371 else version(X86_64) 372 va_start(q, __va_argsave); 373 else 374 static assert(false, "platform not supported"); 375 363 376 void[] foo(TypeInfo ti, size_t* pdim, int ndims) 364 377 { 365 378 size_t dim = *pdim; … … 1167 1180 } 1168 1181 result = gc_malloc(length * sizeelem, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm); 1169 1182 1170 va_list q; 1171 va_start!(size_t)(q, length); 1183 version(X86) 1184 { 1185 va_list q; 1186 va_start!(size_t)(q, length); 1172 1187 1173 size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1);1188 size_t stacksize = (sizeelem + int.sizeof - 1) & ~(int.sizeof - 1); 1174 1189 1175 if (stacksize == sizeelem) 1176 { 1177 memcpy(result, q, length * sizeelem); 1190 if (stacksize == sizeelem) 1191 { 1192 memcpy(result, q, length * sizeelem); 1193 } 1194 else 1195 { 1196 for (size_t i = 0; i < length; i++) 1197 { 1198 memcpy(result + i * sizeelem, q, sizeelem); 1199 q += stacksize; 1200 } 1201 } 1202 1203 va_end(q); 1178 1204 } 1179 else 1205 else version(X86_64) 1180 1206 { 1207 va_list q; 1208 va_start(q, __va_argsave); 1181 1209 for (size_t i = 0; i < length; i++) 1182 1210 { 1183 memcpy(result + i * sizeelem, q, sizeelem); 1184 q += stacksize; 1211 va_arg(q, ti.next, result + i * sizeelem); 1185 1212 } 1213 va_end(q); 1186 1214 } 1187 1188 va_end(q);1189 1215 } 1190 1216 return result; 1191 1217 } -
tango/core/rt/compiler/dmd/rt/aaA.d
old new 110 110 111 111 size_t aligntsize(size_t tsize) 112 112 { 113 // Is pointer alignment on the x64 4 bytes or 8? 114 return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 113 version (X86_64) 114 // Size of key needed to align value on 16 bytes 115 return (tsize + 15) & ~(15); 116 else 117 return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 115 118 } 116 119 117 120 extern (C): … … 824 827 else 825 828 { 826 829 va_list q; 827 v a_start!(size_t)(q, length);830 version(X86_64) va_start(q, __va_argsave); else va_start!(size_t)(q, length); 828 831 829 832 result = new BB(); 830 833 result.keyti = keyti; -
tango/core/rt/compiler/dmd/object_.d
old new 473 473 474 474 /// Get type information on the contents of the type; null if not available 475 475 OffsetTypeInfo[] offTi() { return null; } 476 477 478 /** Return internal info on arguments fitting into 8byte. 479 * See X86-64 ABI 3.2.3 480 */ 481 version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) 482 { arg1 = this; 483 return 0; 484 } 476 485 } 477 486 478 487 class TypeInfo_Typedef : TypeInfo -
tango/core/Variant.d
old new 37 37 version=EnableVararg; 38 38 } 39 39 } 40 version( X86_64 ) 41 { 42 version( Windows ) 43 { 44 version=EnableVararg; 45 } 46 else version( Posix ) 47 { 48 version=EnableVararg; 49 } 50 } 40 51 } 41 52 else version( LDC ) 42 53 { -
tango/core/Thread.d
old new 348 348 { 349 349 __builtin_unwind_init(); 350 350 } 351 else version ( D_InlineAsm_X86_64 ) 352 { 353 asm 354 { 355 // Not sure what goes here, pushad is invalid in 64 bit code 356 push RAX ; 357 push RBX ; 358 push RCX ; 359 push RDX ; 360 push RSI ; 361 push RDI ; 362 push RBP ; 363 push R8 ; 364 push R9 ; 365 push R10 ; 366 push R11 ; 367 push R12 ; 368 push R13 ; 369 push R14 ; 370 push R15 ; 371 push EAX ; // 16 byte align the stack 372 } 373 } 351 374 else 352 375 { 353 376 static assert( false, "Architecture not supported." ); … … 411 434 { 412 435 // registers will be popped automatically 413 436 } 437 else version ( D_InlineAsm_X86_64 ) 438 { 439 asm 440 { 441 // Not sure what goes here, popad is invalid in 64 bit code 442 pop EAX ; // 16 byte align the stack 443 pop R15 ; 444 pop R14 ; 445 pop R13 ; 446 pop R12 ; 447 pop R11 ; 448 pop R10 ; 449 pop R9 ; 450 pop R8 ; 451 pop RBP ; 452 pop RDI ; 453 pop RSI ; 454 pop RDX ; 455 pop RCX ; 456 pop RBX ; 457 pop RAX ; 458 } 459 } 414 460 else 415 461 { 416 462 static assert( false, "Architecture not supported." ); … … 2670 2716 } 2671 2717 else version( AsmX86_64_Posix ) 2672 2718 { 2673 asm2719 version( DigitalMars ) asm 2674 2720 { 2675 2721 naked; 2676 2722 2677 2723 // save current stack state 2724 push RBP; 2725 mov RBP, RSP; 2726 push RBX; 2727 push R12; 2728 push R13; 2729 push R14; 2730 push R15; 2731 sub RSP, 4; 2732 stmxcsr [RSP]; 2733 sub RSP, 4; 2734 //version(SynchroFloatExcept){ 2735 fstcw [RSP]; 2736 fwait; 2737 //} else { 2738 // fnstcw [RSP]; 2739 // fnclex; 2740 //} 2741 2742 // store oldp again with more accurate address 2743 mov [RDI], RSP; 2744 // load newp to begin context switch 2745 mov RSP, RSI; 2746 2747 // load saved state from new stack 2748 fldcw [RSP]; 2749 add RSP, 4; 2750 ldmxcsr [RSP]; 2751 add RSP, 4; 2752 pop R15; 2753 pop R14; 2754 pop R13; 2755 pop R12; 2756 2757 pop RBX; 2758 pop RBP; 2759 2760 // 'return' to complete switch 2761 ret; 2762 2763 } 2764 else asm 2765 { 2766 naked; 2767 2768 // save current stack state 2678 2769 pushq RBP; 2679 2770 mov RBP, RSP; 2680 2771 pushq RBX; -
tango/core/Vararg.d
old new 21 21 } 22 22 else 23 23 { 24 /** 25 * The base vararg list type. 26 */ 24 version (X86) 25 { 27 26 alias void* va_list; 28 27 29 30 /** 31 * This function initializes the supplied argument pointer for subsequent 32 * use by va_arg and va_end. 33 * 34 * Params: 35 * ap = The argument pointer to initialize. 36 * paramn = The identifier of the rightmost parameter in the function 37 * parameter list. 38 */ 39 void va_start(T) ( out va_list ap, ref T parmn ) 28 template va_arg(T) 40 29 { 41 ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 30 T va_arg(inout va_list _argptr) 31 { 32 T arg = *cast(T*)_argptr; 33 _argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1)); 34 return arg; 35 } 42 36 } 37 } 38 else 39 { 40 public import tango.stdc.stdarg; 41 } 43 42 44 /**45 * This function returns the next argument in the sequence referenced by46 * the supplied argument pointer. The argument pointer will be adjusted47 * to point to the next arggument in the sequence.48 *49 * Params:50 * ap = The argument pointer.51 *52 * Returns:53 * The next argument in the sequence. The result is undefined if ap54 * does not point to a valid argument.55 */56 T va_arg(T) ( ref va_list ap )57 {58 T arg = *cast(T*) ap;59 ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) );60 return arg;61 }62 63 /**64 * This function cleans up any resources allocated by va_start. It is65 * currently a no-op and exists mostly for syntax compatibility with66 * the variadric argument functions for C.67 *68 * Params:69 * ap = The argument pointer.70 */71 void va_end( va_list ap )72 {73 74 }75 76 77 /**78 * This function copied the argument pointer src to dst.79 *80 * Params:81 * src = The source pointer.82 * dst = The destination pointer.83 */84 void va_copy( out va_list dst, va_list src )85 {86 dst = src;87 }88 43 } -
tango/stdc/stdarg.d
old new 8 8 */ 9 9 module tango.stdc.stdarg; 10 10 11 12 11 version( GNU ) 13 12 { 14 13 public import std.c.stdarg; … … 19 18 } 20 19 else 21 20 { 21 version (X86) 22 { 23 /********************* 24 * The argument pointer type. 25 */ 22 26 alias void* va_list; 23 27 24 template va_start( T ) 28 /********** 29 * Initialize ap. 30 * For 32 bit code, parmn should be the last named parameter. 31 * For 64 bit code, parmn should be __va_argsave. 32 */ 33 void va_start(T)(out va_list ap, inout T parmn) 25 34 { 26 void va_start( out va_list ap, ref T parmn ) 35 ap = cast(va_list)(cast(void*)&parmn + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 36 } 37 38 /************ 39 * Retrieve and return the next value that is type T. 40 * Should use the other va_arg instead, as this won't work for 64 bit code. 41 */ 42 T va_arg(T)(inout va_list ap) 43 { 44 T arg = *cast(T*)ap; 45 ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 46 return arg; 47 } 48 49 /************ 50 * Retrieve and return the next value that is type T. 51 * This is the preferred version. 52 */ 53 void va_arg(T)(inout va_list ap, inout T parmn) 54 { 55 parmn = *cast(T*)ap; 56 ap = cast(va_list)(cast(void*)ap + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1))); 57 } 58 59 /************* 60 * Retrieve and store through parmn the next value that is of TypeInfo ti. 61 * Used when the static type is not known. 62 */ 63 void va_arg()(inout va_list ap, TypeInfo ti, void* parmn) 64 { 65 // Wait until everyone updates to get TypeInfo.talign() 66 //auto talign = ti.talign(); 67 //auto p = cast(void*)(cast(size_t)ap + talign - 1) & ~(talign - 1); 68 auto p = ap; 69 auto tsize = ti.tsize(); 70 ap = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 71 parmn[0..tsize] = p[0..tsize]; 72 } 73 74 /*********************** 75 * End use of ap. 76 */ 77 void va_end(va_list ap) 78 { 79 } 80 81 void va_copy(out va_list dest, va_list src) 82 { 83 dest = src; 84 } 85 } 86 else version (X86_64) 87 { 88 // Layout of this struct must match __gnuc_va_list for C ABI compatibility 89 struct __va_list 90 { 91 uint offset_regs = 6 * 8; // no regs 92 uint offset_fpregs = 6 * 8 + 8 * 16; // no fp regs 93 void* stack_args; 94 void* reg_args; 95 } 96 97 struct __va_argsave_t 98 { 99 size_t[6] regs; // RDI,RSI,RDX,RCX,R8,R9 100 real[8] fpregs; // XMM0..XMM7 101 __va_list va; 102 } 103 104 /* 105 * Making it an array of 1 causes va_list to be passed as a pointer in 106 * function argument lists 107 */ 108 alias void* va_list; 109 110 void va_start(T)(out va_list ap, inout T parmn) 111 { 112 ap = &parmn.va; 113 } 114 115 T va_arg(T)(va_list ap) 116 { T a; 117 va_arg(ap, a); 118 return a; 119 } 120 121 void va_arg(T)(va_list apx, inout T parmn) 122 { 123 __va_list* ap = cast(__va_list*)apx; 124 static if (is(T U == __argTypes)) 27 125 { 28 ap = cast(va_list) ( cast(void*) &parmn + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 126 static if (U.length == 0 || T.sizeof > 16 || U[0].sizeof > 8) 127 { // Always passed in memory 128 // The arg may have more strict alignment than the stack 129 auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); 130 ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 131 parmn = *cast(T*)p; 132 } 133 else static if (U.length == 1) 134 { // Arg is passed in one register 135 alias U[0] T1; 136 static if (is(T1 == double) || is(T1 == float)) 137 { // Passed in XMM register 138 if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 139 { 140 parmn = *cast(T*)(ap.reg_args + ap.offset_fpregs); 141 ap.offset_fpregs += 16; 142 } 143 else 144 { 145 parmn = *cast(T*)ap.stack_args; 146 ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 147 } 148 } 149 else 150 { // Passed in regular register 151 if (ap.offset_regs < 6 * 8 && T.sizeof <= 8) 152 { 153 parmn = *cast(T*)(ap.reg_args + ap.offset_regs); 154 ap.offset_regs += 8; 155 } 156 else 157 { 158 auto p = (cast(size_t)ap.stack_args + T.alignof - 1) & ~(T.alignof - 1); 159 ap.stack_args = cast(void*)(p + ((T.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 160 parmn = *cast(T*)p; 161 } 162 } 163 } 164 else static if (U.length == 2) 165 { // Arg is passed in two registers 166 alias U[0] T1; 167 alias U[1] T2; 168 169 static if (is(T1 == double) || is(T1 == float)) 170 { 171 if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 172 { 173 *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_fpregs); 174 ap.offset_fpregs += 16; 175 } 176 else 177 { 178 *cast(T1*)&parmn = *cast(T1*)ap.stack_args; 179 ap.stack_args += (T1.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 180 } 181 } 182 else 183 { 184 if (ap.offset_regs < 6 * 8 && T1.sizeof <= 8) 185 { 186 *cast(T1*)&parmn = *cast(T1*)(ap.reg_args + ap.offset_regs); 187 ap.offset_regs += 8; 188 } 189 else 190 { 191 *cast(T1*)&parmn = *cast(T1*)ap.stack_args; 192 ap.stack_args += 8; 193 } 194 } 195 196 auto p = cast(void*)&parmn + 8; 197 static if (is(T2 == double) || is(T2 == float)) 198 { 199 if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 200 { 201 *cast(T2*)p = *cast(T2*)(ap.reg_args + ap.offset_fpregs); 202 ap.offset_fpregs += 16; 203 } 204 else 205 { 206 *cast(T2*)p = *cast(T2*)ap.stack_args; 207 ap.stack_args += (T2.sizeof + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 208 } 209 } 210 else 211 { 212 void* a = void; 213 if (ap.offset_regs < 6 * 8 && T2.sizeof <= 8) 214 { 215 a = ap.reg_args + ap.offset_regs; 216 ap.offset_regs += 8; 217 } 218 else 219 { 220 a = ap.stack_args; 221 ap.stack_args += 8; 222 } 223 // Be careful not to go past the size of the actual argument 224 const sz2 = T.sizeof - 8; 225 p[0..sz2] = a[0..sz2]; 226 } 227 } 228 else 229 { 230 static assert(0); 231 } 29 232 } 233 else 234 { 235 static assert(0, "not a valid argument type for va_arg"); 236 } 30 237 } 31 238 32 template va_arg( T)239 void va_arg()(va_list apx, TypeInfo ti, void* parmn) 33 240 { 34 T va_arg( ref va_list ap ) 241 __va_list* ap = cast(__va_list*)apx; 242 TypeInfo arg1, arg2; 243 if (!ti.argTypes(arg1, arg2)) 35 244 { 36 T arg = *cast(T*) ap; 37 ap = cast(va_list) ( cast(void*) ap + ( ( T.sizeof + int.sizeof - 1 ) & ~( int.sizeof - 1 ) ) ); 38 return arg; 245 if (arg1 && arg1.tsize() <= 8) 246 { // Arg is passed in one register 247 auto tsize = arg1.tsize(); 248 void* p; 249 auto s = arg1.toString(); 250 if (s == "double" || s == "float") 251 { // Passed in XMM register 252 if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 253 { 254 p = ap.reg_args + ap.offset_fpregs; 255 ap.offset_fpregs += 16; 256 } 257 else 258 { 259 p = ap.stack_args; 260 ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 261 } 262 } 263 else 264 { // Passed in regular register 265 if (ap.offset_regs < 6 * 8) 266 { 267 p = ap.reg_args + ap.offset_regs; 268 ap.offset_regs += 8; 269 } 270 else 271 { 272 p = ap.stack_args; 273 ap.stack_args += 8; 274 } 275 } 276 parmn[0..tsize] = p[0..tsize]; 277 278 if (arg2) 279 { 280 parmn += 8; 281 tsize = arg2.tsize(); 282 s = arg2.toString(); 283 if (s == "double" || s == "float") 284 { // Passed in XMM register 285 if (ap.offset_fpregs < (6 * 8 + 16 * 8)) 286 { 287 p = ap.reg_args + ap.offset_fpregs; 288 ap.offset_fpregs += 16; 289 } 290 else 291 { 292 p = ap.stack_args; 293 ap.stack_args += (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); 294 } 295 } 296 else 297 { // Passed in regular register 298 if (ap.offset_regs < 6 * 8) 299 { 300 p = ap.reg_args + ap.offset_regs; 301 ap.offset_regs += 8; 302 } 303 else 304 { 305 p = ap.stack_args; 306 ap.stack_args += 8; 307 } 308 } 309 tsize = ti.tsize() - 8; 310 parmn[0..tsize] = p[0..tsize]; 311 } 312 } 313 else 314 { // Always passed in memory 315 // The arg may have more strict alignment than the stack 316 auto talign = ti.talign(); 317 auto tsize = ti.tsize(); 318 auto p = cast(void*)((cast(size_t)ap.stack_args + talign - 1) & ~(talign - 1)); 319 ap.stack_args = cast(void*)(cast(size_t)p + ((tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1))); 320 parmn[0..tsize] = p[0..tsize]; 321 } 39 322 } 323 else 324 { 325 assert(0, "not a valid argument type for va_arg"); 326 } 40 327 } 41 328 42 void va_end( va_list ap)329 void va_end(va_list ap) 43 330 { 44 45 331 } 46 332 47 void va_copy( out va_list dest, va_list src)333 void va_copy(out va_list dest, va_list src) 48 334 { 49 335 dest = src; 50 336 } 51 337 } 338 else 339 { 340 static assert(0); 341 } 342 }