Changeset 579
- Timestamp:
- 07/17/10 09:30:24 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cgcod.c (modified) (3 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (5 diffs)
- branches/dmd-1.x/src/backend/cod2.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod3.c (modified) (8 diffs)
- branches/dmd-1.x/src/backend/elfobj.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/el.h (modified) (1 diff)
- branches/dmd-1.x/src/backend/symbol.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/ty.h (modified) (1 diff)
- branches/dmd-1.x/src/e2ir.c (modified) (4 diffs)
- branches/dmd-1.x/src/msc.c (modified) (1 diff)
- trunk/src/backend/cgcod.c (modified) (3 diffs)
- trunk/src/backend/cod1.c (modified) (5 diffs)
- trunk/src/backend/cod2.c (modified) (1 diff)
- trunk/src/backend/cod3.c (modified) (8 diffs)
- trunk/src/backend/elfobj.c (modified) (1 diff)
- trunk/src/backend/el.h (modified) (1 diff)
- trunk/src/backend/symbol.c (modified) (1 diff)
- trunk/src/backend/ty.h (modified) (1 diff)
- trunk/src/e2ir.c (modified) (4 diffs)
- trunk/src/msc.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cgcod.c
r577 r579 123 123 // in that basic block. 124 124 125 125 //printf("codgen('%s')\n",funcsym_p->Sident); 126 126 127 127 cgreg_init(); 128 128 csmax = 64; 129 129 csextab = (struct CSE *) util_calloc(sizeof(struct CSE),csmax); 130 130 functy = tybasic(funcsym_p->ty()); 131 131 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 132 132 if (0 && config.flags3 & CFG3pic) 133 133 { 134 134 ALLREGS = ALLREGS_INIT_PIC; 135 135 BYTEREGS = BYTEREGS_INIT_PIC; 136 136 } 137 137 else 138 138 { 139 139 regm_t value = BYTEREGS_INIT; 140 140 ALLREGS = ALLREGS_INIT; 141 141 BYTEREGS = value; 142 142 } 143 if (I64) 144 ALLREGS = mAX|mBX|mCX|mDX|mSI|mDI| mR8|mR9|mR10|mR11|mR12|mR13|mR14|mR15; 143 145 #endif 144 146 allregs = ALLREGS; 145 147 if (0 && config.flags3 & CFG3pic) 146 148 allregs &= ~mBX; 147 149 pass = PASSinit; 148 150 149 151 tryagain: 150 152 #ifdef DEBUG 151 153 if (debugr) 152 154 printf("------------------ PASS%s -----------------\n", 153 155 (pass == PASSinit) ? "init" : ((pass == PASSreg) ? "reg" : "final")); 154 156 #endif 155 157 lastretregs = last2retregs = last3retregs = last4retregs = last5retregs = 0; 156 158 157 159 // if no parameters, assume we don't need a stack frame 158 160 needframe = 0; 159 161 usedalloca = 0; 160 162 gotref = 0; 161 163 stackchanged = 0; 162 164 stackpush = 0; … … 1901 1903 { retregs &= mMSW; 1902 1904 goto L3; 1903 1905 } 1904 1906 } 1905 1907 reg = (msreg == ES) ? lsreg : msreg; 1906 1908 retregs = mask[msreg] | mask[lsreg]; 1907 1909 } 1908 1910 else if (I16 && (tym == TYdouble || tym == TYdouble_alias)) 1909 1911 { 1910 1912 #ifdef DEBUG 1911 1913 if (retregs != DOUBLEREGS) 1912 1914 printf("retregs = x%x, *pretregs = x%x\n",retregs,*pretregs); 1913 1915 #endif 1914 1916 assert(retregs == DOUBLEREGS); 1915 1917 reg = AX; 1916 1918 } 1917 1919 else 1918 1920 { 1919 1921 #ifdef DEBUG 1920 1922 WRTYxx(tym); 1921 printf("\nallocreg: fil %s lin %d, regcon.mvar x%x msavereg x%x *pretregs x%x, reg %d, tym x% lx\n",1923 printf("\nallocreg: fil %s lin %d, regcon.mvar x%x msavereg x%x *pretregs x%x, reg %d, tym x%x\n", 1922 1924 file,line,regcon.mvar,msavereg,*pretregs,*preg,tym); 1923 1925 #endif 1924 1926 assert(0); 1925 1927 } 1926 1928 if (retregs & regcon.mvar) // if conflict with reg vars 1927 1929 { 1928 1930 if (!(size > REGSIZE && *pretregs == (mAX | mDX))) 1929 1931 { 1930 1932 retregs = (*pretregs &= ~(retregs & regcon.mvar)); 1931 1933 goto L1; // try other registers 1932 1934 } 1933 1935 } 1934 1936 *preg = reg; 1935 1937 *pretregs = retregs; 1936 1938 1937 1939 //printf("Allocating %s\n",regm_str(retregs)); 1938 1940 last5retregs = last4retregs; 1939 1941 last4retregs = last3retregs; 1940 1942 last3retregs = last2retregs; 1941 1943 last2retregs = lastretregs; … … 2470 2472 assert(I16); 2471 2473 if (((csemask | emask) & DOUBLEREGS_16) == DOUBLEREGS_16) 2472 2474 { 2473 2475 for (reg = AX; reg != -1; reg = dblreg[reg]) 2474 2476 { assert((int) reg >= 0 && reg <= 7); 2475 2477 if (mask[reg] & csemask) 2476 2478 c = cat(c,loadcse(e,reg,mask[reg])); 2477 2479 } 2478 2480 regm = DOUBLEREGS_16; 2479 2481 goto fix; 2480 2482 } 2481 2483 if (!EOP(e)) goto reload; 2482 2484 #if DEBUG 2483 2485 printf("e = %p, csemask = x%x, emask = x%x\n",e,csemask,emask); 2484 2486 #endif 2485 2487 assert(0); 2486 2488 } 2487 2489 else 2488 2490 { 2489 2491 #if DEBUG 2490 printf("e = %p, tym = x% lx\n",e,tym);2492 printf("e = %p, tym = x%x\n",e,tym); 2491 2493 #endif 2492 2494 assert(0); 2493 2495 } 2494 2496 2495 2497 reload: /* reload result from memory */ 2496 2498 switch (e->Eoper) 2497 2499 { 2498 2500 case OPrelconst: 2499 2501 c = cdrelconst(e,pretregs); 2500 2502 break; 2501 2503 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 2502 2504 case OPgot: 2503 2505 c = cdgot(e,pretregs); 2504 2506 break; 2505 2507 #endif 2506 2508 default: 2507 2509 c = loaddata(e,pretregs); 2508 2510 break; 2509 2511 } 2510 2512 cssave(e,*pretregs,FALSE); branches/dmd-1.x/src/backend/cod1.c
r577 r579 1 1 // Copyright (C) 1984-1998 by Symantec 2 2 // Copyright (C) 2000-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // http://www.digitalmars.com 5 5 // Written by Walter Bright 6 6 /* 7 7 * This source file is made available for personal use 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 #if !SPP 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 #include <stdlib.h> 17 18 #include <time.h> 18 19 #include "cc.h" 19 20 #include "el.h" 20 21 #include "oper.h" 21 22 #include "code.h" 22 23 #include "global.h" 23 24 #include "type.h" 24 25 25 26 static char __file__[] = __FILE__; /* for tassert.h */ 26 27 #include "tassert.h" 27 28 28 29 targ_size_t paramsize(elem *e,unsigned stackalign); 29 30 STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 30 31 31 32 /* array to convert from index register to r/m field */ 32 33 /* AX CX DX BX SP BP SI DI */ 33 34 static const signed char regtorm32[8] = { 0, 1, 2, 3,-1, 5, 6, 7 }; 34 35 signed char regtorm [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 35 36 36 37 /************************** … … 309 310 stackpushsave = stackpush; 310 311 stackcleansave = cgstate.stackclean; 311 312 cgstate.stackclean = 0; // defer cleaning of stack 312 313 c = cat(c,codelem(e,pretregs,constflag)); 313 314 assert(cgstate.stackclean == 0); 314 315 cgstate.stackclean = stackcleansave; 315 316 c = genstackclean(c,stackpush - stackpushsave,*pretregs); // do defered cleaning 316 317 } 317 318 return c; 318 319 } 319 320 320 321 /******************************************** 321 322 * Gen a save/restore sequence for mask of registers. 322 323 */ 323 324 324 325 void gensaverestore2(regm_t regm,code **csave,code **crestore) 325 326 { 326 327 code *cs1 = *csave; 327 328 code *cs2 = *crestore; 328 329 330 //printf("gensaverestore2(%x)\n", regm); 329 331 regm &= mBP | mES | ALLREGS; 330 332 for (int i = 0; regm; i++) 331 333 { 332 334 if (regm & 1) 333 335 { 334 336 if (i == ES) 335 337 { 336 338 cs1 = gen1(cs1, 0x06); // PUSH ES 337 339 cs2 = cat(gen1(CNIL, 0x07),cs2); // POP ES 338 340 } 339 341 else 340 342 { 341 343 cs1 = gen1(cs1,0x50 + (i & 7)); // PUSH i 342 344 code *c = gen1(NULL, 0x58 + (i & 7)); // POP i 343 345 if (i & 8) 344 346 { code_orrex(cs1, REX_B); 345 347 code_orrex(c, REX_B); 346 348 } 347 349 cs2 = cat(c,cs2); 348 350 } … … 1648 1650 } 1649 1651 } 1650 1652 return c; 1651 1653 } 1652 1654 1653 1655 1654 1656 /***************************** 1655 1657 * Given a result in registers, test it for TRUE or FALSE. 1656 1658 * Will fail if TYfptr and the reg is ES! 1657 1659 * If saveflag is TRUE, preserve the contents of the 1658 1660 * registers. 1659 1661 */ 1660 1662 1661 1663 code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 1662 1664 { 1663 1665 unsigned scrreg; /* scratch register */ 1664 1666 regm_t scrregm; 1665 1667 1666 1668 #ifdef DEBUG 1667 1669 if (!(regm & (mBP | ALLREGS))) 1668 printf("tstresult(regm = x%x, tym = x% lx, saveflag = %d)\n",1670 printf("tstresult(regm = x%x, tym = x%x, saveflag = %d)\n", 1669 1671 regm,tym,saveflag); 1670 1672 #endif 1671 1673 assert(regm & (mBP | ALLREGS)); 1672 1674 tym = tybasic(tym); 1673 1675 code *ce = CNIL; 1674 1676 unsigned reg = findreg(regm); 1675 1677 unsigned sz = tysize[tym]; 1676 1678 if (sz == 1) 1677 1679 { assert(regm & BYTEREGS); 1678 1680 return genregs(ce,0x84,reg,reg); // TEST regL,regL 1679 1681 } 1680 1682 if (sz <= REGSIZE) 1681 1683 { 1682 1684 if (!I16) 1683 1685 { 1684 1686 if (tym == TYfloat) 1685 1687 { if (saveflag) 1686 1688 { 1687 1689 scrregm = allregs & ~regm; /* possible scratch regs */ 1688 1690 ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ … … 2292 2294 2293 2295 /******************************* 2294 2296 * Generate code sequence for function call. 2295 2297 */ 2296 2298 2297 2299 code *cdfunc(elem *e,regm_t *pretregs) 2298 2300 { unsigned numpara = 0; 2299 2301 unsigned stackpushsave; 2300 2302 unsigned preg; 2301 2303 regm_t keepmsk; 2302 2304 unsigned numalign = 0; 2303 2305 code *c; 2304 2306 2305 2307 //printf("cdfunc()\n"); elem_print(e); 2306 2308 assert(e); 2307 2309 stackpushsave = stackpush; /* so we can compute # of parameters */ 2308 2310 cgstate.stackclean++; 2309 2311 c = CNIL; 2310 2312 keepmsk = 0; 2311 2313 if (OTbinary(e->Eoper)) // if parameters 2312 { unsigned stackalign = REGSIZE; 2313 elem *en; 2314 regm_t retregs; 2315 2316 if (!I16) 2314 { 2315 if (I16) 2317 2316 { 2317 c = cat(c, params(e->E2,2)); // push parameters 2318 } 2319 else if (I32) 2320 { 2321 unsigned stackalign = REGSIZE; 2318 2322 tym_t tyf = tybasic(e->E1->Ety); 2319 2323 2320 // First compute numpara, the total pushed on the stack2324 // First compute numpara, the total bytes pushed on the stack 2321 2325 switch (tyf) 2322 2326 { case TYf16func: 2323 2327 stackalign = 2; 2324 2328 goto Ldefault; 2325 2329 case TYmfunc: 2326 2330 case TYjfunc: 2327 2331 // last parameter goes into register 2328 2332 elem *ep; 2329 2333 for (ep = e->E2; ep->Eoper == OPparam; ep = ep->E2) 2330 2334 { 2331 2335 numpara += paramsize(ep->E1,stackalign); 2332 2336 } 2333 2337 if (tyf == TYjfunc && 2334 2338 // This must match type_jparam() 2335 2339 !(tyjparam(ep->Ety) || 2336 2340 ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 2337 2341 ) 2338 2342 ) 2339 2343 { 2340 2344 numpara += paramsize(ep,stackalign); … … 2348 2352 assert((numpara & (REGSIZE - 1)) == 0); 2349 2353 assert((stackpush & (REGSIZE - 1)) == 0); 2350 2354 2351 2355 /* Adjust start of the stack so after all args are pushed, 2352 2356 * the stack will be aligned. 2353 2357 */ 2354 2358 if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 2355 2359 { 2356 2360 numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 2357 2361 c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 2358 2362 if (I64) 2359 2363 code_orrex(c, REX_W); 2360 2364 c = genadjesp(c, numalign); 2361 2365 stackpush += numalign; 2362 2366 stackpushsave += numalign; 2363 2367 } 2364 2368 2365 2369 switch (tyf) 2366 2370 { case TYf16func: 2367 2371 stackalign = 2; 2368 break;2372 goto Ldefault2; 2369 2373 case TYmfunc: // last parameter goes into ECX 2370 2374 preg = CX; 2371 2375 goto L1; 2372 2376 case TYjfunc: // last parameter goes into EAX 2373 2377 preg = AX; 2374 2378 goto L1; 2375 2379 2376 2380 L1: 2377 elem *ep; 2380 { elem *ep; 2381 elem *en; 2378 2382 for (ep = e->E2; ep->Eoper == OPparam; ep = en) 2379 2383 { 2380 2384 c = cat(c,params(ep->E1,stackalign)); 2381 2385 en = ep->E2; 2382 2386 freenode(ep); 2383 ep = en;2384 2387 } 2385 2388 if (tyf == TYjfunc && 2386 2389 // This must match type_jparam() 2387 2390 !(tyjparam(ep->Ety) || 2388 2391 ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 2389 2392 ) 2390 2393 ) 2391 2394 { 2392 2395 c = cat(c,params(ep,stackalign)); 2393 2396 goto Lret; 2394 2397 } 2395 2398 // preg is the register to put the parameter ep in 2396 2399 keepmsk = mask[preg]; // don't change preg when evaluating func address 2397 re tregs = keepmsk;2400 regm_t retregs = keepmsk; 2398 2401 if (ep->Eoper == OPstrthis) 2399 2402 { code *c2; 2400 2403 2401 2404 code *c1 = getregs(retregs); 2402 2405 // LEA preg,np[ESP] 2403 2406 unsigned np = stackpush - ep->EV.Vuns; // stack delta to parameter 2404 2407 c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregrm(2,preg,4),FLconst,np); 2405 2408 if (I64) 2406 2409 code_orrex(c2, REX_W); 2407 2410 c = cat3(c,c1,c2); 2408 2411 } 2409 2412 else 2410 2413 { code *cp = codelem(ep,&retregs,FALSE); 2411 2414 c = cat(c,cp); 2412 2415 } 2413 2416 goto Lret; 2414 } 2415 } 2416 c = cat(c, params(e->E2,stackalign)); // push parameters 2417 } 2418 default: 2419 Ldefault2: 2420 c = cat(c, params(e->E2,stackalign)); // push parameters 2421 break; 2422 } 2423 } 2424 else 2425 { assert(I64); 2426 2427 struct Parameter { elem *e; int reg; }; 2428 2429 #ifdef DEBUG 2430 #define PARAMETERS_DIM 3 2431 #else 2432 #define PARAMETERS_DIM 10 2433 #endif 2434 Parameter parameters_tmp[PARAMETERS_DIM]; 2435 Parameter *parameters = parameters_tmp; 2436 size_t parameters_dim = PARAMETERS_DIM; 2437 2438 // Load up parameters[] 2439 elem *ep; 2440 elem *en; 2441 int np = 0; 2442 for (ep = e->E2; ep->Eoper == OPparam; ep = en) 2443 { 2444 if (np + 1 == parameters_dim) // if not space for 2 more 2445 { // Grow parameters[] 2446 parameters_dim = np + 16; 2447 Parameter *p = (Parameter *)alloca(parameters_dim * sizeof(Parameter)); 2448 parameters = (Parameter *)memcpy(p, parameters, np * sizeof(Parameter)); 2449 } 2450 parameters[np++].e = ep->E1; 2451 en = ep->E2; 2452 freenode(ep); 2453 } 2454 parameters[np++].e = ep; 2455 2456 unsigned stackalign = REGSIZE; 2457 tym_t tyf = tybasic(e->E1->Ety); 2458 2459 // Compute numpara, the total bytes pushed on the stack 2460 int r = 0; 2461 int xmmcnt = XMM0; 2462 for (int i = np; --i >= 0;) 2463 { 2464 static const unsigned char argregs[6] = { DI,SI,DX,CX,R8,R9 }; 2465 elem *ep = parameters[i].e; 2466 tym_t ty = ep->Ety; 2467 if (r < sizeof(argregs)/sizeof(argregs[0])) // if more arg regs 2468 { 2469 if ( 2470 // This must match type_jparam() 2471 ty64reg(ty) || 2472 ((tybasic(ty) == TYstruct || tybasic(ty) == TYarray) && 2473 ep->Enumbytes <= REGSIZE && ep->Enumbytes != 3 && ep->Enumbytes) 2474 ) 2475 { 2476 parameters[i].reg = argregs[r]; 2477 r++; 2478 continue; // goes in register, not stack 2479 } 2480 } 2481 else if (xmmcnt < XMM7) 2482 { 2483 if (tyfloating(ty) && tysize(ty) <= 8) 2484 { 2485 parameters[i].reg = xmmcnt; 2486 xmmcnt++; 2487 continue; // goes in register, not stack 2488 } 2489 } 2490 parameters[i].reg = -1; // -1 means no register 2491 numpara += paramsize(ep,stackalign); 2492 } 2493 assert((numpara & (REGSIZE - 1)) == 0); 2494 assert((stackpush & (REGSIZE - 1)) == 0); 2495 2496 /* Adjust start of the stack so after all args are pushed, 2497 * the stack will be aligned. 2498 */ 2499 if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 2500 { 2501 numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 2502 c = genc2(NULL,0x81,(REX_W << 16) | modregrm(3,5,SP),numalign); // SUB ESP,numalign 2503 c = genadjesp(c, numalign); 2504 stackpush += numalign; 2505 stackpushsave += numalign; 2506 } 2507 2508 /* Parameters go into the registers RDI,RSI,RDX,RCX,R8,R9 2509 * float and double parameters go into XMM0..XMM7 2510 * For variadic functions, count of XMM registers used goes in AL 2511 */ 2512 for (int i = 0; i < np; i++) 2513 { 2514 elem *ep = parameters[i].e; 2515 int preg = parameters[i].reg; 2516 if (preg == -1) 2517 c = cat(c,params(ep,stackalign)); 2518 else 2519 { 2520 // Goes in register preg, not stack 2521 regm_t retregs = mask[preg]; 2522 if (ep->Eoper == OPstrthis) 2523 { 2524 code *c1 = getregs(retregs); 2525 // LEA preg,np[ESP] 2526 unsigned np = stackpush - ep->EV.Vuns; // stack delta to parameter 2527 code *c2 = genc1(CNIL,0x8D,(REX_W << 16) | 2528 (modregrm(0,4,SP) << 8) | 2529 modregxrm(2,preg,4), FLconst,np); 2530 c = cat3(c,c1,c2); 2531 } 2532 else 2533 { code *cp = scodelem(ep,&retregs,keepmsk,FALSE); 2534 c = cat(c,cp); 2535 } 2536 keepmsk |= retregs; // don't change preg when evaluating func address 2537 } 2538 } 2539 if (e->Eflags & EFLAGS_variadic) 2540 { movregconst(c,AX,xmmcnt - XMM0,1); 2541 keepmsk |= mAX; 2542 } 2543 } 2417 2544 } 2418 2545 else 2419 2546 { 2420 2547 /* Adjust start of the stack so 2421 2548 * the stack will be aligned. 2422 2549 */ 2423 2550 if (STACKALIGN == 16 && (stackpush) & (STACKALIGN - 1)) 2424 2551 { 2425 2552 numalign = STACKALIGN - ((stackpush) & (STACKALIGN - 1)); 2426 2553 c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 2427 2554 if (I64) 2428 2555 code_orrex(c, REX_W); 2429 2556 c = genadjesp(c, numalign); 2430 2557 stackpush += numalign; 2431 2558 stackpushsave += numalign; 2432 2559 } 2433 2560 2434 2561 } 2435 2562 Lret: 2436 2563 cgstate.stackclean--; 2437 if (!I16) 2564 if (I16) 2565 numpara = stackpush - stackpushsave; 2566 else 2438 2567 { 2439 2568 if (numpara != stackpush - stackpushsave) 2440 2569 printf("numpara = %d, stackpush = %d, stackpushsave = %d\n", numpara, stackpush, stackpushsave); 2441 2570 assert(numpara == stackpush - stackpushsave); 2442 2571 } 2443 else2444 numpara = stackpush - stackpushsave;2445 2572 return cat(c,funccall(e,numpara,numalign,pretregs,keepmsk)); 2446 2573 } 2447 2574 2448 2575 /*********************************** 2449 2576 */ 2450 2577 2451 2578 code *cdstrthis(elem *e,regm_t *pretregs) 2452 2579 { 2453 2580 code *c1; 2454 2581 code *c2; 2455 2582 2456 2583 assert(tysize(e->Ety) == REGSIZE); 2457 2584 unsigned reg = findreg(*pretregs & allregs); 2458 2585 c1 = getregs(mask[reg]); 2459 2586 // LEA reg,np[ESP] 2460 2587 unsigned np = stackpush - e->EV.Vuns; // stack delta to parameter 2461 2588 c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregxrm(2,reg,4),FLconst,np); 2462 2589 if (I64) 2463 2590 code_orrex(c2, REX_W); 2464 2591 return cat3(c1,c2,fixresult(e,mask[reg],pretregs)); branches/dmd-1.x/src/backend/cod2.c
r577 r579 3720 3720 fl = FLcsdata; 3721 3721 c = gen2(c,0x8C, /* MOV mreg,SEG REGISTER */ 3722 3722 modregrm(3,segfl[fl],mreg)); 3723 3723 } 3724 3724 if (*pretregs & mES) 3725 3725 gen2(c,0x8E,modregrm(3,0,mreg)); /* MOV ES,mreg */ 3726 3726 } 3727 3727 return cat(c,getoffset(e,lreg)); 3728 3728 } 3729 3729 3730 3730 /********************************* 3731 3731 * Load the offset portion of the address represented by e into 3732 3732 * reg. 3733 3733 */ 3734 3734 3735 3735 code *getoffset(elem *e,unsigned reg) 3736 3736 { code cs; 3737 3737 code *c; 3738 3738 3739 3739 cs.Iflags = 0; 3740 unsigned char rex = I64 ? REX_W :0;3740 unsigned char rex = 0; 3741 3741 cs.Irex = rex; 3742 3742 assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 3743 3743 enum FL fl = el_fl(e); 3744 3744 switch (fl) 3745 3745 { 3746 3746 case FLdatseg: 3747 3747 cs.IEV2._EP.Vpointer = e->EV.Vpointer; 3748 3748 goto L3; 3749 3749 3750 3750 case FLfardata: 3751 3751 assert(!TARGET_FLAT); 3752 3752 goto L4; 3753 3753 3754 3754 case FLtlsdata: 3755 3755 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 3756 3756 { /* Generate: 3757 3757 * MOV reg,GS:[00000000] 3758 3758 * ADD reg, offset s@TLS_LE 3759 3759 * for locals, and for globals: 3760 3760 * MOV reg,GS:[00000000] branches/dmd-1.x/src/backend/cod3.c
r577 r579 1159 1159 { p[0] = len; 1160 1160 memcpy(p + 1,name,len); 1161 1161 len++; 1162 1162 } 1163 1163 return len; 1164 1164 } 1165 1165 #endif 1166 1166 1167 1167 /******************************* 1168 1168 * Generate code for a function start. 1169 1169 * Input: 1170 1170 * Coffset address of start of code 1171 1171 * Output: 1172 1172 * Coffset adjusted for size of code generated 1173 1173 * EBPtoESP 1174 1174 * hasframe 1175 1175 * BPoff 1176 1176 */ 1177 1177 1178 1178 code *prolog() 1179 { code *c;1179 { 1180 1180 SYMIDX si; 1181 1181 unsigned reg; 1182 regm_t topush;1183 tym_t tym;1184 tym_t tyf;1185 1182 char enter; 1186 char pushds;1187 unsigned farfunc;1188 1183 unsigned Foffset; 1189 1184 unsigned xlocalsize; // amount to subtract from ESP to make room for locals 1190 int pushalloc;1191 1185 unsigned pushallocreg; 1192 1186 char guessneedframe; 1193 1187 1194 1188 //printf("cod3.prolog(), needframe = %d, Aalign = %d\n", needframe, Aalign); 1195 1189 debugx(debugw && printf("funcstart()\n")); 1196 1190 regcon.immed.mval = 0; /* no values in registers yet */ 1197 1191 EBPtoESP = -REGSIZE; 1198 1192 hasframe = 0; 1199 pushds = 0;1193 char pushds = 0; 1200 1194 BPoff = 0; 1201 c = CNIL;1202 pushalloc = 0;1203 ty f = funcsym_p->ty();1204 tym = tybasic(tyf);1205 farfunc = tyfarfunc(tym);1195 code *c = CNIL; 1196 int pushalloc = 0; 1197 tym_t tyf = funcsym_p->ty(); 1198 tym_t tym = tybasic(tyf); 1199 unsigned farfunc = tyfarfunc(tym); 1206 1200 pushallocreg = (tyf == TYmfunc) ? CX : AX; 1207 1201 if (config.flags & CFGalwaysframe || funcsym_p->Sfunc->Fflags3 & Ffakeeh) 1208 1202 needframe = 1; 1209 1203 1210 1204 Lagain: 1211 1205 guessneedframe = needframe; 1212 1206 // if (needframe && config.exe & (EX_LINUX | EX_FREEBSD | EX_SOLARIS) && !(usednteh & ~NTEHjmonitor)) 1213 1207 // usednteh |= NTEHpassthru; 1214 1208 1215 1209 /* Compute BP offsets for variables on stack. 1216 1210 * The organization is: 1217 1211 * Poff parameters 1218 1212 * seg of return addr (if far function) 1219 1213 * IP of return addr 1220 1214 * BP-> caller's BP 1221 1215 * DS (if Windows prolog/epilog) 1222 1216 * exception handling context symbol 1223 1217 * Aoff autos and regs 1224 1218 * Foff floating register 1225 1219 * AAoff alloca temporary … … 1251 1245 1252 1246 if (Aalign > REGSIZE) 1253 1247 { 1254 1248 // Adjust Aoff so that it is Aalign byte aligned, assuming that 1255 1249 // before function parameters were pushed the stack was 1256 1250 // Aalign byte aligned 1257 1251 int sz = Poffset + -Aoff + Poff + (needframe ? 0 : REGSIZE); 1258 1252 if (sz & (Aalign - 1)) 1259 1253 Aoff -= sz - (sz & (Aalign - 1)); 1260 1254 } 1261 1255 1262 1256 Foffset = floatreg ? DOUBLESIZE : 0; 1263 1257 Foff = Aoff - align(0,Foffset); 1264 1258 assert(usedalloca != 1); 1265 1259 AAoff = usedalloca ? (Foff - REGSIZE) : Foff; 1266 1260 CSoff = AAoff - align(0,cstop * REGSIZE); 1267 1261 NDPoff = CSoff - align(0,NDP::savetop * NDPSAVESIZE); 1268 1262 Toff = NDPoff - align(0,Toffset); 1269 1263 localsize = -Toff; 1270 1264 1271 topush = fregsaved & ~mfuncreg; // mask of registers that need saving1265 regm_t topush = fregsaved & ~mfuncreg; // mask of registers that need saving 1272 1266 int npush = 0; // number of registers that need saving 1273 1267 for (regm_t x = topush; x; x >>= 1) 1274 1268 npush += x & 1; 1275 1269 1276 1270 // Keep the stack aligned by 8 for any subsequent function calls 1277 1271 if (!I16 && calledafunc && 1278 1272 (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 1279 1273 { 1280 1274 //printf("npush = %d Poff = x%x needframe = %d localsize = x%x\n", npush, Poff, needframe, localsize); 1281 1275 1282 1276 int sz = Poff + (needframe ? 0 : -REGSIZE) + localsize + npush * REGSIZE; 1283 1277 if (STACKALIGN == 16) 1284 1278 { 1285 1279 if (sz & (8|4)) 1286 1280 localsize += STACKALIGN - (sz & (8|4)); 1287 1281 } 1288 1282 else if (sz & 4) 1289 1283 localsize += 4; 1290 1284 } 1291 1285 … … 1333 1327 farfunc || 1334 1328 config.flags & CFGstack || 1335 1329 xlocalsize >= 0x1000 || 1336 1330 (usednteh & ~NTEHjmonitor) || 1337 1331 anyiasm || 1338 1332 usedalloca 1339 1333 ) 1340 1334 needframe = 1; 1341 1335 } 1342 1336 if (refparam && (anyiasm || I16)) 1343 1337 needframe = 1; 1344 1338 } 1345 1339 1346 1340 if (needframe) 1347 1341 { assert(mfuncreg & mBP); // shouldn't have used mBP 1348 1342 1349 1343 if (!guessneedframe) // if guessed wrong 1350 1344 goto Lagain; 1351 1345 } 1352 1346 1353 #if SIXTEENBIT 1354 if (config.wflags & WFwindows && farfunc) 1347 if (I16 && config.wflags & WFwindows && farfunc) 1355 1348 { int wflags; 1356 1349 int segreg; 1357 1350 1351 #if SCPP 1358 1352 // alloca() can't be because the 'special' parameter won't be at 1359 1353 // a known offset from BP. 1360 1354 if (usedalloca == 1) 1361 1355 synerr(EM_alloca_win); // alloca() can't be in Windows functions 1356 #endif 1362 1357 1363 1358 wflags = config.wflags; 1364 1359 if (wflags & WFreduced && !(tyf & mTYexport)) 1365 1360 { // reduced prolog/epilog for non-exported functions 1366 1361 wflags &= ~(WFdgroup | WFds | WFss); 1367 1362 } 1368 1363 1369 1364 c = getregs(mAX); 1370 1365 assert(!c); /* should not have any value in AX */ 1371 1366 1372 1367 switch (wflags & (WFdgroup | WFds | WFss)) 1373 1368 { case WFdgroup: // MOV AX,DGROUP 1374 1369 if (wflags & WFreduced) 1375 1370 tyf &= ~mTYloadds; // remove redundancy 1376 1371 c = genc(c,0xC7,modregrm(3,0,AX),0,0,FLdatseg,(targ_uns) 0); 1377 1372 c->Iflags ^= CFseg | CFoff; // turn off CFoff, on CFseg 1378 1373 break; 1379 1374 case WFss: 1380 1375 segreg = 2; // SS 1381 1376 goto Lmovax; … … 1393 1388 printf("config.wflags = x%x\n",config.wflags); 1394 1389 #endif 1395 1390 assert(0); 1396 1391 } 1397 1392 if (wflags & WFincbp) 1398 1393 c = gen1(c,0x40 + BP); // INC BP 1399 1394 c = gen1(c,0x50 + BP); // PUSH BP 1400 1395 genregs(c,0x8B,BP,SP); // MOV BP,SP 1401 1396 if (wflags & (WFsaveds | WFds | WFss | WFdgroup)) 1402 1397 { gen1(c,0x1E); // PUSH DS 1403 1398 pushds = TRUE; 1404 1399 BPoff = -REGSIZE; 1405 1400 } 1406 1401 if (wflags & (WFds | WFss | WFdgroup)) 1407 1402 gen2(c,0x8E,modregrm(3,3,AX)); // MOV DS,AX 1408 1403 1409 1404 enter = FALSE; /* don't use ENTER instruction */ 1410 1405 hasframe = 1; /* we have a stack frame */ 1411 1406 } 1412 1407 else 1413 #endif1414 1408 if (needframe) // if variables or parameters 1415 1409 { 1416 1410 if (config.wflags & WFincbp && farfunc) 1417 1411 c = gen1(c,0x40 + BP); /* INC BP */ 1418 1412 if (config.target_cpu < TARGET_80286 || 1419 1413 config.exe & (EX_LINUX | EX_LINUX64 | EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | EX_SOLARIS | EX_SOLARIS64) || 1420 1414 !localsize || 1421 1415 config.flags & CFGstack || 1422 1416 (xlocalsize >= 0x1000 && config.exe & EX_flat) || 1423 1417 localsize >= 0x10000 || 1424 1418 #if NTEXCEPTIONS == 2 1425 1419 (usednteh & ~NTEHjmonitor && (config.flags2 & CFG2seh)) || 1426 1420 #endif 1427 1421 (config.target_cpu >= TARGET_80386 && 1428 1422 config.flags4 & CFG4speed) 1429 1423 ) 1430 1424 { 1431 1425 c = gen1(c,0x50 + BP); // PUSH BP 1432 1426 genregs(c,0x8B,BP,SP); // MOV BP,SP 1433 1427 if (I64) … … 1647 1641 } 1648 1642 1649 1643 #if MARS 1650 1644 if (usednteh & NTEHjmonitor) 1651 1645 { Symbol *sthis; 1652 1646 1653 1647 for (si = 0; 1; si++) 1654 1648 { assert(si < globsym.top); 1655 1649 sthis = globsym.tab[si]; 1656 1650 if (strcmp(sthis->Sident,"this") == 0) 1657 1651 break; 1658 1652 } 1659 1653 c = cat(c,nteh_monitor_prolog(sthis)); 1660 1654 EBPtoESP += 3 * 4; 1661 1655 } 1662 1656 #endif 1663 1657 1664 1658 while (topush) /* while registers to push */ 1665 1659 { reg = findreg(topush); 1666 1660 topush &= ~mask[reg]; 1667 c = gen1(c,0x50 + reg); 1661 c = gen1(c,0x50 + (reg & 7)); 1662 if (reg & 8) 1663 code_orrex(c, REX_B); 1668 1664 EBPtoESP += REGSIZE; 1669 1665 #if ELFOBJ || MACHOBJ 1670 1666 if (config.fulltypes) 1671 1667 { // Emit debug_frame data giving location of saved register 1672 1668 // relative to 0[EBP] 1673 1669 pinholeopt(c, NULL); 1674 1670 dwarf_CFA_set_loc(calcblksize(c)); // address after PUSH reg 1675 1671 dwarf_CFA_offset(reg, -EBPtoESP - REGSIZE); 1676 1672 } 1677 1673 #endif 1678 1674 } 1679 1675 1680 1676 Lcont: 1681 1677 1682 1678 /* Determine if we need to reload DS */ 1683 1679 if (tyf & mTYloadds) 1684 1680 { code *c1; 1685 1681 1686 1682 if (!pushds) // if not already pushed 1687 1683 c = gen1(c,0x1E); // PUSH DS … … 1900 1896 if (tyf & mTYloadds) 1901 1897 { cpopds = gen1(cpopds,0x1F); // POP DS 1902 1898 c = cat(c,cpopds); 1903 1899 spoff += intsize; 1904 1900 } 1905 1901 1906 1902 /* Pop all the general purpose registers saved on the stack 1907 1903 * by the prolog code. Remember to do them in the reverse 1908 1904 * order they were pushed. 1909 1905 */ 1910 1906 reg = I64 ? R15 : DI; 1911 1907 regm = 1 << reg; 1912 1908 topop = fregsaved & ~mfuncreg; 1913 1909 #ifdef DEBUG 1914 1910 if (topop & ~0xFFFF) 1915 1911 printf("fregsaved = x%x, mfuncreg = x%x\n",fregsaved,mfuncreg); 1916 1912 #endif 1917 1913 assert(!(topop & ~0xFFFF)); 1918 1914 while (topop) 1919 1915 { if (topop & regm) 1920 { c = gen1(c,0x58 + reg); // POP reg1916 { c = gen1(c,0x58 + (reg & 7)); // POP reg 1921 1917 if (reg & 8) 1922 1918 code_orrex(c, REX_B); 1923 1919 topop &= ~regm; 1924 1920 spoff += intsize; 1925 1921 } 1926 1922 regm >>= 1; 1927 1923 reg--; 1928 1924 } 1929 1925 1930 1926 #if MARS 1931 1927 if (usednteh & NTEHjmonitor) 1932 1928 { 1933 1929 regm_t retregs = 0; 1934 1930 if (b->BC == BCretexp) 1935 1931 retregs = regmask(b->Belem->Ety, tym); 1936 1932 code *cn = nteh_monitor_epilog(retregs); 1937 1933 c = cat(c,cn); 1938 1934 xlocalsize += 8; 1939 1935 } 1940 1936 #endif … … 4342 4338 #ifdef DEBUG 4343 4339 assert(uev->Vblock->Boffset > OFFSET() || c != 0x7F); 4344 4340 #endif 4345 4341 break; 4346 4342 default: 4347 4343 #ifdef DEBUG 4348 4344 fprintf(stderr,"fl = %d\n",fl); 4349 4345 #endif 4350 4346 assert(0); 4351 4347 } 4352 4348 GEN(c); 4353 4349 } 4354 4350 4355 4351 4356 4352 /**************************** 4357 4353 * Add to the fix list. 4358 4354 */ 4359 4355 4360 4356 void addtofixlist(symbol *s,targ_size_t soffset,int seg,targ_size_t val,int flags) 4361 4357 { fixlist *ln; 4362 static char zeros[ 6];4358 static char zeros[8]; 4363 4359 int numbytes; 4364 4360 4365 4361 //printf("addtofixlist(%p '%s')\n",s,s->Sident); 4366 4362 assert(flags); 4367 4363 ln = (fixlist *) mem_calloc(sizeof(fixlist)); 4368 4364 ln->Lsymbol = s; 4369 4365 ln->Loffset = soffset; 4370 4366 ln->Lseg = seg; 4371 4367 ln->Lflags = flags; 4372 4368 ln->Lval = val; 4373 4369 #if TARGET_OSX 4374 4370 ln->Lfuncsym = funcsym_p; 4375 4371 #endif 4376 4372 ln->Lnext = fixlist::start; 4377 4373 fixlist::start = ln; 4378 4374 #if TARGET_FLAT 4379 4375 numbytes = tysize[TYnptr]; 4380 4376 assert(!(flags & CFseg)); 4381 4377 #else 4382 4378 switch (flags & (CFoff | CFseg)) … … 4880 4876 { printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 4881 4877 return; 4882 4878 } 4883 4879 printf(" ESCAPE %d",c->Iop2); 4884 4880 } 4885 4881 if (c->Iflags) 4886 4882 printf(" flg=%x",c->Iflags); 4887 4883 if (ins & M) 4888 4884 { rm = c->Irm; 4889 4885 printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 4890 4886 if (I32 && issib(rm)) 4891 4887 { unsigned char sib = c->Isib; 4892 4888 printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 4893 4889 } 4894 4890 if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 4895 4891 { 4896 4892 switch (c->IFL1) 4897 4893 { 4898 4894 case FLconst: 4899 4895 case FLoffset: 4900 printf(" int = %4 ld",c->IEV1.Vuns);4896 printf(" int = %4d",c->IEV1.Vuns); 4901 4897 break; 4902 4898 case FLblock: 4903 4899 printf(" block = %p",c->IEV1.Vblock); 4904 4900 break; 4905 4901 case FLswitch: 4906 4902 case FLblockoff: 4907 4903 case FLlocalsize: 4908 4904 case FLframehandler: 4909 4905 case 0: 4910 4906 break; 4911 4907 case FLdatseg: 4912 4908 printf(" %d.%lx",c->IEVseg1,c->IEVpointer1); 4913 4909 break; 4914 4910 case FLauto: 4915 4911 case FLreg: 4916 4912 case FLdata: 4917 4913 case FLudata: 4918 4914 case FLpara: 4919 4915 case FLtmp: 4920 4916 case FLbprel: 4921 4917 case FLtlsdata: 4922 4918 printf(" sym='%s'",c->IEVsym1->Sident); 4923 4919 break; 4924 4920 default: 4925 4921 WRFL((enum FL)c->IFL1); 4926 4922 break; 4927 4923 } 4928 4924 } 4929 4925 } 4930 4926 if (ins & T) 4931 4927 { printf(" "); WRFL((enum FL)c->IFL2); 4932 4928 switch (c->IFL2) 4933 4929 { 4934 4930 case FLconst: 4935 printf(" int = %4 ld",c->IEV2.Vuns);4931 printf(" int = %4d",c->IEV2.Vuns); 4936 4932 break; 4937 4933 case FLblock: 4938 4934 printf(" block = %p",c->IEV2.Vblock); 4939 4935 break; 4940 4936 case FLswitch: 4941 4937 case FLblockoff: 4942 4938 case 0: 4943 4939 case FLlocalsize: 4944 4940 case FLframehandler: 4945 4941 break; 4946 4942 case FLdatseg: 4947 4943 printf(" %d.%lx",c->IEVseg2,c->IEVpointer2); 4948 4944 break; 4949 4945 case FLauto: 4950 4946 case FLreg: 4951 4947 case FLpara: 4952 4948 case FLtmp: 4953 4949 case FLbprel: 4954 4950 case FLfunc: 4955 4951 case FLdata: branches/dmd-1.x/src/backend/elfobj.c
r572 r579 2701 2701 offset = (foffset + 31) & ~31; 2702 2702 break; 2703 2703 default: 2704 2704 dbg_printf("size was %d\n",(int)size); 2705 2705 assert(0); 2706 2706 break; 2707 2707 } 2708 2708 if (offset > foffset) 2709 2709 fobjbuf->writezeros(offset - foffset); 2710 2710 return offset; 2711 2711 } 2712 2712 2713 2713 /*************************************** 2714 2714 * Stuff pointer to ModuleInfo in its own segment. 2715 2715 */ 2716 2716 2717 2717 #if MARS 2718 2718 2719 2719 void obj_moduleinfo(Symbol *scc) 2720 2720 { 2721 // if (I64) return; // for now, until Phobos64 works 2722 2721 2723 int codeOffset, refOffset; 2722 2724 2723 2725 /* Put in the ModuleReference. */ 2724 2726 { 2725 2727 /* struct ModuleReference 2726 2728 * { 2727 2729 * void* next; 2728 2730 * ModuleReference* module; 2729 2731 * } 2730 2732 */ 2731 2733 const int seg = DATA; 2732 2734 alignOffset(seg, NPTRSIZE); 2733 2735 SegData[seg]->SDoffset = SegData[seg]->SDbuf->size(); 2734 2736 refOffset = SegData[seg]->SDoffset; 2735 2737 SegData[seg]->SDbuf->writezeros(NPTRSIZE); 2736 2738 SegData[seg]->SDoffset += NPTRSIZE; 2737 SegData[seg]->SDoffset += reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFoff); 2738 alignOffset(seg, NPTRSIZE); 2739 SegData[seg]->SDoffset += reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFoffset64 | CFoff); 2739 2740 } 2740 2741 2741 2742 /* Constructor that links the ModuleReference to the head of 2742 2743 * the list pointed to by _Dmoduleref 2743 2744 */ 2744 2745 { 2745 2746 /* ret 2746 2747 * codeOffset: 2747 2748 * pushad 2748 2749 * mov EAX,&ModuleReference 2749 2750 * mov ECX,_DmoduleRef 2750 2751 * mov EDX,[ECX] 2751 2752 * mov [EAX],EDX 2752 2753 * mov [ECX],EAX 2753 2754 * popad 2754 2755 * ret 2755 2756 */ 2756 2757 2757 2758 const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2758 2759 const int refsize = 4; // use 32 bit relocations, even in 64 bit mode 2759 2760 2760 2761 const int seg = CODE; 2761 2762 Outbuffer *buf = SegData[seg]->SDbuf; 2762 2763 SegData[seg]->SDoffset = buf->size(); 2763 2764 codeOffset = SegData[seg]->SDoffset + 1; 2764 2765 buf->writeByte(0xC3); /* ret */ 2765 2766 2766 buf->writeByte(0x60); /* pushad */ 2767 int off = 0; 2768 if (I32) 2769 { buf->writeByte(0x60); // PUSHAD 2770 off = 1; 2771 } 2767 2772 2768 2773 /* movl ModuleReference*, %eax */ 2769 2774 buf->writeByte(0xB8); 2770 2775 buf->write32(refOffset); 2771 elf_addrel(seg, codeOffset + 2, reltype, STI_DATA, 0);2776 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2772 2777 2773 2778 /* movl _Dmodule_ref, %ecx */ 2774 2779 buf->writeByte(0xB9); 2775 2780 buf->write32(0); 2776 elf_addrel(seg, codeOffset + 7, reltype, objextern("_Dmodule_ref"), 0);2781 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2777 2782 2778 2783 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2779 2784 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2780 2785 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2781 2786 2782 buf->writeByte(0x61); /* popad */2787 if (I32) buf->writeByte(0x61); // POPAD 2783 2788 buf->writeByte(0xC3); /* ret */ 2784 2789 SegData[seg]->SDoffset = buf->size(); 2785 2790 } 2786 2791 2787 2792 /* Add reference to constructor into ".ctors" segment 2788 2793 */ 2789 2794 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 2790 2795 2791 2796 Outbuffer *buf = SegData[seg]->SDbuf; 2792 2797 buf->write32(codeOffset); 2793 2798 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 2794 2799 SegData[seg]->SDoffset += NPTRSIZE; 2795 2800 } 2796 2801 2797 2802 #endif 2798 2803 2799 2804 /************************************* 2800 2805 */ 2801 2806 2802 2807 void elfobj_gotref(symbol *s) branches/dmd-1.x/src/backend/el.h
r572 r579 26 26 /****************************************** 27 27 * Elems: 28 28 * Elems are the basic tree element. They can be either 29 29 * terminal elems (leaves), unary elems (left subtree exists) 30 30 * or binary elems (left and right subtrees exist). 31 31 */ 32 32 33 33 struct elem 34 34 { 35 35 #ifdef DEBUG 36 36 unsigned short id; 37 37 #define IDelem 0x4C45 // 'EL' 38 38 #define elem_debug(e) assert((e)->id == IDelem) 39 39 #else 40 40 #define elem_debug(e) 41 41 #endif 42 42 43 43 unsigned char Eoper; // operator (OPxxxx) 44 44 unsigned char Ecount; // # of parents of this elem - 1, 45 45 // always 0 until CSE elimination is done 46 unsigned char Eflags; 47 #define EFLAGS_variadic 1 // variadic function call 48 46 49 union eve EV; // variants for each type of elem 47 50 union 48 51 { 49 52 // PARSER 50 53 struct 51 54 { 52 55 struct TYPE *ET_; // pointer to type of elem 53 56 #define ET _EU._EP.ET_ 54 57 55 58 unsigned PEFflags_; 56 59 #define PEFflags _EU._EP.PEFflags_ 57 60 #define PEFnotlvalue 1 // although elem may look like 58 61 // an lvalue, it isn't 59 62 #define PEFtemplate_id 0x10 // symbol is a template-id 60 63 #define PEFparentheses 0x20 // expression was within () 61 64 #define PEFaddrmem 0x40 // address of member 62 65 #define PEFdependent 0x80 // value-dependent 63 66 #define PEFmember 0x100 // was a class member access 64 67 #if !TX86 65 68 #define PEFdblldbl 2 // long double return from dbl func branches/dmd-1.x/src/backend/symbol.c
r487 r579 346 346 Symbol *symbol_genauto(elem *e) 347 347 { 348 348 return symbol_genauto(type_fake(e->Ety)); 349 349 } 350 350 351 351 /****************************************** 352 352 * Generate symbol into which we can copy the contents of expression e. 353 353 */ 354 354 355 355 Symbol *symbol_genauto(tym_t ty) 356 356 { 357 357 return symbol_genauto(type_fake(ty)); 358 358 } 359 359 360 360 /**************************************** 361 361 * Add in the variants for a function symbol. 362 362 */ 363 363 364 364 void symbol_func(symbol *s) 365 365 { 366 //printf("symbol_func(%s, x%x)\n", s->Sident, fregsaved); 366 367 symbol_debug(s); 367 368 s->Sfl = FLfunc; 368 369 // Interrupt functions modify all registers 369 370 #if TX86 370 371 // BUG: do interrupt functions really save BP? 371 372 #define mBP 0x20 373 // Note that fregsaved may not be set yet 372 374 s->Sregsaved = (s->Stype && tybasic(s->Stype->Tty) == TYifunc) ? mBP : fregsaved; 373 375 s->Sseg = UNKNOWN; // don't know what segment it is in 374 376 #endif 375 377 if (!s->Sfunc) 376 378 s->Sfunc = func_calloc(); 377 379 } 378 380 379 381 /******************************** 380 382 * Define symbol in specified symbol table. 381 383 * Returns: 382 384 * pointer to symbol 383 385 */ 384 386 385 387 #if SCPP 386 388 387 389 symbol * defsy(const char *p,symbol **parent) 388 390 { 389 391 symbol *s = symbol_calloc(p); 390 392 symbol_addtotree(parent,s); 391 393 return s; branches/dmd-1.x/src/backend/ty.h
r557 r579 180 180 #define TYFLref 0x8000 181 181 182 182 /* Groupings of types */ 183 183 184 184 #define tyintegral(ty) (tytab[(ty) & 0xFF] & TYFLintegral) 185 185 186 186 #define tyarithmetic(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLreal | TYFLimaginary | TYFLcomplex)) 187 187 188 188 #define tyaggregate(ty) (tytab[(ty) & 0xFF] & TYFLaggregate) 189 189 190 190 #define tyscalar(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLreal | TYFLimaginary | TYFLcomplex | TYFLptr | TYFLmptr | TYFLnullptr)) 191 191 192 192 #define tyfloating(ty) (tytab[(ty) & 0xFF] & (TYFLreal | TYFLimaginary | TYFLcomplex)) 193 193 194 194 #define tyimaginary(ty) (tytab[(ty) & 0xFF] & TYFLimaginary) 195 195 196 196 #define tycomplex(ty) (tytab[(ty) & 0xFF] & TYFLcomplex) 197 197 198 198 #define tyreal(ty) (tytab[(ty) & 0xFF] & TYFLreal) 199 199 200 // Fits into 64 bit register 201 #define ty64reg(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLptr)) 202 200 203 #ifndef tyshort 201 204 /* Types that are chars or shorts */ 202 205 #define tyshort(ty) (tytab[(ty) & 0xFF] & TYFLshort) 203 206 #endif 204 207 205 208 /* Detect TYlong or TYulong */ 206 209 #ifndef tylong 207 210 #define tylong(ty) (tybasic(ty) == TYlong || tybasic(ty) == TYulong) 208 211 #endif 209 212 210 213 /* Use to detect a pointer type */ 211 214 #ifndef typtr 212 215 #define typtr(ty) (tytab[(ty) & 0xFF] & TYFLptr) 213 216 #endif 214 217 215 218 /* Use to detect a reference type */ 216 219 #ifndef tyref 217 220 #define tyref(ty) (tytab[(ty) & 0xFF] & TYFLref) 218 221 #endif 219 222 branches/dmd-1.x/src/e2ir.c
r569 r579 263 263 ep->Ety = tyret; 264 264 e = ep; 265 265 if (op == OPscale) 266 266 { 267 267 elem *et = e->E1; 268 268 e->E1 = el_una(OPs32_d, TYdouble, e->E2); 269 269 e->E1 = el_una(OPd_ld, TYldouble, e->E1); 270 270 e->E2 = et; 271 271 } 272 272 else if (op == OPyl2x || op == OPyl2xp1) 273 273 { 274 274 elem *et = e->E1; 275 275 e->E1 = e->E2; 276 276 e->E2 = et; 277 277 } 278 278 } 279 279 else 280 280 e = el_una(op,tyret,ep); 281 281 } 282 282 else if (ep) 283 e = el_bin(OPcall,tyret,ec,ep); 283 { e = el_bin(OPcall,tyret,ec,ep); 284 if (tf->varargs) 285 e->Eflags |= EFLAGS_variadic; 286 } 284 287 else 285 e = el_una(OPucall,tyret,ec); 288 { e = el_una(OPucall,tyret,ec); 289 if (tf->varargs) 290 e->Eflags |= EFLAGS_variadic; 291 } 286 292 287 293 if (retmethod == RETstack) 288 294 { 289 295 e->Ety = TYnptr; 290 296 e = el_una(OPind, tyret, e); 291 297 } 292 298 293 299 #if DMDV2 294 300 if (tf->isref) 295 301 { 296 302 e->Ety = TYnptr; 297 303 e = el_una(OPind, tyret, e); 298 304 } 299 305 #endif 300 306 301 307 if (tybasic(tyret) == TYstruct) 302 308 { 303 309 e->Enumbytes = tret->size(); 304 310 } 305 311 e = el_combine(eside, e); … … 1756 1762 { 1757 1763 elem *ep; 1758 1764 CatExp *ce = this; 1759 1765 int n = 2; 1760 1766 1761 1767 ep = eval_Darray(irs, ce->e2); 1762 1768 do 1763 1769 { 1764 1770 n++; 1765 1771 ce = (CatExp *)ce->e1; 1766 1772 ep = el_param(ep, eval_Darray(irs, ce->e2)); 1767 1773 } while (ce->e1->op == TOKcat); 1768 1774 ep = el_param(ep, eval_Darray(irs, ce->e1)); 1769 1775 #if 1 1770 1776 ep = el_params( 1771 1777 ep, 1772 1778 el_long(TYint, n), 1773 1779 ta->getTypeInfo(NULL)->toElem(irs), 1774 1780 NULL); 1775 1781 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep); 1782 e->Eflags |= EFLAGS_variadic; 1776 1783 #else 1777 1784 ep = el_params( 1778 1785 ep, 1779 1786 el_long(TYint, n), 1780 1787 el_long(TYint, tn->size()), 1781 1788 NULL); 1782 1789 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep); 1790 e->Eflags |= EFLAGS_variadic; 1783 1791 #endif 1784 1792 } 1785 1793 else 1786 1794 { 1787 1795 elem *e1; 1788 1796 elem *e2; 1789 1797 elem *ep; 1790 1798 1791 1799 e1 = eval_Darray(irs, this->e1); 1792 1800 e2 = eval_Darray(irs, this->e2); 1793 1801 #if 1 1794 1802 ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL); 1795 1803 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep); 1796 1804 #else 1797 1805 ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL); 1798 1806 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep); 1799 1807 #endif 1800 1808 } 1801 1809 el_setLoc(e,loc); 1802 1810 } … … 4200 4208 } 4201 4209 args.data[dim - (i + 1)] = (void *)ep; 4202 4210 } 4203 4211 4204 4212 /* Because the number of parameters can get very large, produce 4205 4213 * a balanced binary tree so we don't blow up the stack in 4206 4214 * the subsequent tree walking code. 4207 4215 */ 4208 4216 e = el_params(args.data, dim + 1); 4209 4217 } 4210 4218 else 4211 4219 { dim = 0; 4212 4220 e = el_long(TYint, 0); 4213 4221 } 4214 4222 Type *tb = type->toBasetype(); 4215 4223 #if 1 4216 4224 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); 4217 4225 4218 4226 // call _d_arrayliteralT(ti, dim, ...) 4219 4227 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e); 4228 e->Eflags |= EFLAGS_variadic; 4220 4229 #else 4221 4230 e = el_param(e, el_long(TYint, tb->next->size())); 4222 4231 4223 4232 // call _d_arrayliteral(size, dim, ...) 4224 4233 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e); 4234 e->Eflags |= EFLAGS_variadic; 4225 4235 #endif 4226 4236 if (tb->ty == Tarray) 4227 4237 { 4228 4238 e = el_pair(TYullong, el_long(TYint, dim), e); 4229 4239 } 4230 4240 else if (tb->ty == Tpointer) 4231 4241 { 4232 4242 } 4233 4243 else 4234 4244 { 4235 4245 e = el_una(OPind,TYstruct,e); 4236 4246 e->Enumbytes = type->size(); 4237 4247 } 4238 4248 4239 4249 el_setLoc(e,loc); 4240 4250 return e; 4241 4251 } 4242 4252 4243 4253 4244 4254 elem *AssocArrayLiteralExp::toElem(IRState *irs) … … 4253 4263 4254 4264 for (int j = 0; j < 2; j++) 4255 4265 { 4256 4266 elem *ep = el->toElem(irs); 4257 4267 4258 4268 if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) 4259 4269 { 4260 4270 ep = el_una(OPstrpar, TYstruct, ep); 4261 4271 ep->Enumbytes = el->type->size(); 4262 4272 } 4263 4273 //printf("[%d] %s\n", i, el->toChars()); 4264 4274 //elem_print(ep); 4265 4275 e = el_param(ep, e); 4266 4276 el = (Expression *)values->data[i]; 4267 4277 } 4268 4278 } 4269 4279 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); 4270 4280 4271 4281 // call _d_assocarrayliteralT(ti, dim, ...) 4272 4282 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e); 4283 e->Eflags |= EFLAGS_variadic; 4273 4284 4274 4285 el_setLoc(e,loc); 4275 4286 return e; 4276 4287 } 4277 4288 4278 4289 4279 4290 /******************************************* 4280 4291 * Generate elem to zero fill contents of Symbol stmp 4281 4292 * from *poffset..offset2. 4282 4293 * May store anywhere from 0..maxoff, as this function 4283 4294 * tries to use aligned int stores whereever possible. 4284 4295 * Update *poffset to end of initialized hole; *poffset will be >= offset2. 4285 4296 */ 4286 4297 4287 4298 elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff) 4288 4299 { elem *e = NULL; 4289 4300 int basealign = 1; 4290 4301 4291 4302 while (*poffset < offset2) 4292 4303 { tym_t ty; branches/dmd-1.x/src/msc.c
r569 r579 23 23 #include "dt.h" 24 24 #include "cgcv.h" 25 25 26 26 static char __file__[] = __FILE__; /* for tassert.h */ 27 27 #include "tassert.h" 28 28 29 29 extern Global global; 30 30 extern int REALSIZE; 31 31 32 32 Config config; 33 33 Configv configv; 34 34 35 35 struct Environment; 36 36 37 37 /************************************** 38 38 * Initialize config variables. 39 39 */ 40 40 41 41 void out_config_init() 42 42 { 43 //printf("out_config_init()\n"); 43 44 Param *params = &global.params; 44 45 45 46 if (!config.target_cpu) 46 47 { config.target_cpu = TARGET_PentiumPro; 47 48 config.target_scheduler = config.target_cpu; 48 49 } 49 50 config.fulltypes = CVNONE; 50 51 config.inline8087 = 1; 51 52 config.memmodel = 0; 52 53 config.flags |= CFGuchar; // make sure TYchar is unsigned 53 54 #if TARGET_WINDOS 54 55 if (params->isX86_64) 55 56 config.exe = EX_WIN64; 56 57 else 57 58 config.exe = EX_NT; 58 59 59 60 // Win32 eh 60 61 config.flags2 |= CFG2seh; 61 62 62 63 if (params->run) trunk/src/backend/cgcod.c
r577 r579 123 123 // in that basic block. 124 124 125 125 //printf("codgen('%s')\n",funcsym_p->Sident); 126 126 127 127 cgreg_init(); 128 128 csmax = 64; 129 129 csextab = (struct CSE *) util_calloc(sizeof(struct CSE),csmax); 130 130 functy = tybasic(funcsym_p->ty()); 131 131 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 132 132 if (0 && config.flags3 & CFG3pic) 133 133 { 134 134 ALLREGS = ALLREGS_INIT_PIC; 135 135 BYTEREGS = BYTEREGS_INIT_PIC; 136 136 } 137 137 else 138 138 { 139 139 regm_t value = BYTEREGS_INIT; 140 140 ALLREGS = ALLREGS_INIT; 141 141 BYTEREGS = value; 142 142 } 143 if (I64) 144 ALLREGS = mAX|mBX|mCX|mDX|mSI|mDI| mR8|mR9|mR10|mR11|mR12|mR13|mR14|mR15; 143 145 #endif 144 146 allregs = ALLREGS; 145 147 if (0 && config.flags3 & CFG3pic) 146 148 allregs &= ~mBX; 147 149 pass = PASSinit; 148 150 149 151 tryagain: 150 152 #ifdef DEBUG 151 153 if (debugr) 152 154 printf("------------------ PASS%s -----------------\n", 153 155 (pass == PASSinit) ? "init" : ((pass == PASSreg) ? "reg" : "final")); 154 156 #endif 155 157 lastretregs = last2retregs = last3retregs = last4retregs = last5retregs = 0; 156 158 157 159 // if no parameters, assume we don't need a stack frame 158 160 needframe = 0; 159 161 usedalloca = 0; 160 162 gotref = 0; 161 163 stackchanged = 0; 162 164 stackpush = 0; … … 1901 1903 { retregs &= mMSW; 1902 1904 goto L3; 1903 1905 } 1904 1906 } 1905 1907 reg = (msreg == ES) ? lsreg : msreg; 1906 1908 retregs = mask[msreg] | mask[lsreg]; 1907 1909 } 1908 1910 else if (I16 && (tym == TYdouble || tym == TYdouble_alias)) 1909 1911 { 1910 1912 #ifdef DEBUG 1911 1913 if (retregs != DOUBLEREGS) 1912 1914 printf("retregs = x%x, *pretregs = x%x\n",retregs,*pretregs); 1913 1915 #endif 1914 1916 assert(retregs == DOUBLEREGS); 1915 1917 reg = AX; 1916 1918 } 1917 1919 else 1918 1920 { 1919 1921 #ifdef DEBUG 1920 1922 WRTYxx(tym); 1921 printf("\nallocreg: fil %s lin %d, regcon.mvar x%x msavereg x%x *pretregs x%x, reg %d, tym x% lx\n",1923 printf("\nallocreg: fil %s lin %d, regcon.mvar x%x msavereg x%x *pretregs x%x, reg %d, tym x%x\n", 1922 1924 file,line,regcon.mvar,msavereg,*pretregs,*preg,tym); 1923 1925 #endif 1924 1926 assert(0); 1925 1927 } 1926 1928 if (retregs & regcon.mvar) // if conflict with reg vars 1927 1929 { 1928 1930 if (!(size > REGSIZE && *pretregs == (mAX | mDX))) 1929 1931 { 1930 1932 retregs = (*pretregs &= ~(retregs & regcon.mvar)); 1931 1933 goto L1; // try other registers 1932 1934 } 1933 1935 } 1934 1936 *preg = reg; 1935 1937 *pretregs = retregs; 1936 1938 1937 1939 //printf("Allocating %s\n",regm_str(retregs)); 1938 1940 last5retregs = last4retregs; 1939 1941 last4retregs = last3retregs; 1940 1942 last3retregs = last2retregs; 1941 1943 last2retregs = lastretregs; … … 2470 2472 assert(I16); 2471 2473 if (((csemask | emask) & DOUBLEREGS_16) == DOUBLEREGS_16) 2472 2474 { 2473 2475 for (reg = AX; reg != -1; reg = dblreg[reg]) 2474 2476 { assert((int) reg >= 0 && reg <= 7); 2475 2477 if (mask[reg] & csemask) 2476 2478 c = cat(c,loadcse(e,reg,mask[reg])); 2477 2479 } 2478 2480 regm = DOUBLEREGS_16; 2479 2481 goto fix; 2480 2482 } 2481 2483 if (!EOP(e)) goto reload; 2482 2484 #if DEBUG 2483 2485 printf("e = %p, csemask = x%x, emask = x%x\n",e,csemask,emask); 2484 2486 #endif 2485 2487 assert(0); 2486 2488 } 2487 2489 else 2488 2490 { 2489 2491 #if DEBUG 2490 printf("e = %p, tym = x% lx\n",e,tym);2492 printf("e = %p, tym = x%x\n",e,tym); 2491 2493 #endif 2492 2494 assert(0); 2493 2495 } 2494 2496 2495 2497 reload: /* reload result from memory */ 2496 2498 switch (e->Eoper) 2497 2499 { 2498 2500 case OPrelconst: 2499 2501 c = cdrelconst(e,pretregs); 2500 2502 break; 2501 2503 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 2502 2504 case OPgot: 2503 2505 c = cdgot(e,pretregs); 2504 2506 break; 2505 2507 #endif 2506 2508 default: 2507 2509 c = loaddata(e,pretregs); 2508 2510 break; 2509 2511 } 2510 2512 cssave(e,*pretregs,FALSE); trunk/src/backend/cod1.c
r577 r579 1 1 // Copyright (C) 1984-1998 by Symantec 2 2 // Copyright (C) 2000-2010 by Digital Mars 3 3 // All Rights Reserved 4 4 // http://www.digitalmars.com 5 5 // Written by Walter Bright 6 6 /* 7 7 * This source file is made available for personal use 8 8 * only. The license is in /dmd/src/dmd/backendlicense.txt 9 9 * or /dm/src/dmd/backendlicense.txt 10 10 * For any other uses, please contact Digital Mars. 11 11 */ 12 12 13 13 #if !SPP 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 #include <stdlib.h> 17 18 #include <time.h> 18 19 #include "cc.h" 19 20 #include "el.h" 20 21 #include "oper.h" 21 22 #include "code.h" 22 23 #include "global.h" 23 24 #include "type.h" 24 25 25 26 static char __file__[] = __FILE__; /* for tassert.h */ 26 27 #include "tassert.h" 27 28 28 29 targ_size_t paramsize(elem *e,unsigned stackalign); 29 30 STATIC code * funccall (elem *,unsigned,unsigned,regm_t *,regm_t); 30 31 31 32 /* array to convert from index register to r/m field */ 32 33 /* AX CX DX BX SP BP SI DI */ 33 34 static const signed char regtorm32[8] = { 0, 1, 2, 3,-1, 5, 6, 7 }; 34 35 signed char regtorm [8] = { -1,-1,-1, 7,-1, 6, 4, 5 }; 35 36 36 37 /************************** … … 309 310 stackpushsave = stackpush; 310 311 stackcleansave = cgstate.stackclean; 311 312 cgstate.stackclean = 0; // defer cleaning of stack 312 313 c = cat(c,codelem(e,pretregs,constflag)); 313 314 assert(cgstate.stackclean == 0); 314 315 cgstate.stackclean = stackcleansave; 315 316 c = genstackclean(c,stackpush - stackpushsave,*pretregs); // do defered cleaning 316 317 } 317 318 return c; 318 319 } 319 320 320 321 /******************************************** 321 322 * Gen a save/restore sequence for mask of registers. 322 323 */ 323 324 324 325 void gensaverestore2(regm_t regm,code **csave,code **crestore) 325 326 { 326 327 code *cs1 = *csave; 327 328 code *cs2 = *crestore; 328 329 330 //printf("gensaverestore2(%x)\n", regm); 329 331 regm &= mBP | mES | ALLREGS; 330 332 for (int i = 0; regm; i++) 331 333 { 332 334 if (regm & 1) 333 335 { 334 336 if (i == ES) 335 337 { 336 338 cs1 = gen1(cs1, 0x06); // PUSH ES 337 339 cs2 = cat(gen1(CNIL, 0x07),cs2); // POP ES 338 340 } 339 341 else 340 342 { 341 343 cs1 = gen1(cs1,0x50 + (i & 7)); // PUSH i 342 344 code *c = gen1(NULL, 0x58 + (i & 7)); // POP i 343 345 if (i & 8) 344 346 { code_orrex(cs1, REX_B); 345 347 code_orrex(c, REX_B); 346 348 } 347 349 cs2 = cat(c,cs2); 348 350 } … … 1648 1650 } 1649 1651 } 1650 1652 return c; 1651 1653 } 1652 1654 1653 1655 1654 1656 /***************************** 1655 1657 * Given a result in registers, test it for TRUE or FALSE. 1656 1658 * Will fail if TYfptr and the reg is ES! 1657 1659 * If saveflag is TRUE, preserve the contents of the 1658 1660 * registers. 1659 1661 */ 1660 1662 1661 1663 code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 1662 1664 { 1663 1665 unsigned scrreg; /* scratch register */ 1664 1666 regm_t scrregm; 1665 1667 1666 1668 #ifdef DEBUG 1667 1669 if (!(regm & (mBP | ALLREGS))) 1668 printf("tstresult(regm = x%x, tym = x% lx, saveflag = %d)\n",1670 printf("tstresult(regm = x%x, tym = x%x, saveflag = %d)\n", 1669 1671 regm,tym,saveflag); 1670 1672 #endif 1671 1673 assert(regm & (mBP | ALLREGS)); 1672 1674 tym = tybasic(tym); 1673 1675 code *ce = CNIL; 1674 1676 unsigned reg = findreg(regm); 1675 1677 unsigned sz = tysize[tym]; 1676 1678 if (sz == 1) 1677 1679 { assert(regm & BYTEREGS); 1678 1680 return genregs(ce,0x84,reg,reg); // TEST regL,regL 1679 1681 } 1680 1682 if (sz <= REGSIZE) 1681 1683 { 1682 1684 if (!I16) 1683 1685 { 1684 1686 if (tym == TYfloat) 1685 1687 { if (saveflag) 1686 1688 { 1687 1689 scrregm = allregs & ~regm; /* possible scratch regs */ 1688 1690 ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ … … 2292 2294 2293 2295 /******************************* 2294 2296 * Generate code sequence for function call. 2295 2297 */ 2296 2298 2297 2299 code *cdfunc(elem *e,regm_t *pretregs) 2298 2300 { unsigned numpara = 0; 2299 2301 unsigned stackpushsave; 2300 2302 unsigned preg; 2301 2303 regm_t keepmsk; 2302 2304 unsigned numalign = 0; 2303 2305 code *c; 2304 2306 2305 2307 //printf("cdfunc()\n"); elem_print(e); 2306 2308 assert(e); 2307 2309 stackpushsave = stackpush; /* so we can compute # of parameters */ 2308 2310 cgstate.stackclean++; 2309 2311 c = CNIL; 2310 2312 keepmsk = 0; 2311 2313 if (OTbinary(e->Eoper)) // if parameters 2312 { unsigned stackalign = REGSIZE; 2313 elem *en; 2314 regm_t retregs; 2315 2316 if (!I16) 2314 { 2315 if (I16) 2317 2316 { 2317 c = cat(c, params(e->E2,2)); // push parameters 2318 } 2319 else if (I32) 2320 { 2321 unsigned stackalign = REGSIZE; 2318 2322 tym_t tyf = tybasic(e->E1->Ety); 2319 2323 2320 // First compute numpara, the total pushed on the stack2324 // First compute numpara, the total bytes pushed on the stack 2321 2325 switch (tyf) 2322 2326 { case TYf16func: 2323 2327 stackalign = 2; 2324 2328 goto Ldefault; 2325 2329 case TYmfunc: 2326 2330 case TYjfunc: 2327 2331 // last parameter goes into register 2328 2332 elem *ep; 2329 2333 for (ep = e->E2; ep->Eoper == OPparam; ep = ep->E2) 2330 2334 { 2331 2335 numpara += paramsize(ep->E1,stackalign); 2332 2336 } 2333 2337 if (tyf == TYjfunc && 2334 2338 // This must match type_jparam() 2335 2339 !(tyjparam(ep->Ety) || 2336 2340 ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 2337 2341 ) 2338 2342 ) 2339 2343 { 2340 2344 numpara += paramsize(ep,stackalign); … … 2348 2352 assert((numpara & (REGSIZE - 1)) == 0); 2349 2353 assert((stackpush & (REGSIZE - 1)) == 0); 2350 2354 2351 2355 /* Adjust start of the stack so after all args are pushed, 2352 2356 * the stack will be aligned. 2353 2357 */ 2354 2358 if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 2355 2359 { 2356 2360 numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 2357 2361 c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 2358 2362 if (I64) 2359 2363 code_orrex(c, REX_W); 2360 2364 c = genadjesp(c, numalign); 2361 2365 stackpush += numalign; 2362 2366 stackpushsave += numalign; 2363 2367 } 2364 2368 2365 2369 switch (tyf) 2366 2370 { case TYf16func: 2367 2371 stackalign = 2; 2368 break;2372 goto Ldefault2; 2369 2373 case TYmfunc: // last parameter goes into ECX 2370 2374 preg = CX; 2371 2375 goto L1; 2372 2376 case TYjfunc: // last parameter goes into EAX 2373 2377 preg = AX; 2374 2378 goto L1; 2375 2379 2376 2380 L1: 2377 elem *ep; 2380 { elem *ep; 2381 elem *en; 2378 2382 for (ep = e->E2; ep->Eoper == OPparam; ep = en) 2379 2383 { 2380 2384 c = cat(c,params(ep->E1,stackalign)); 2381 2385 en = ep->E2; 2382 2386 freenode(ep); 2383 ep = en;2384 2387 } 2385 2388 if (tyf == TYjfunc && 2386 2389 // This must match type_jparam() 2387 2390 !(tyjparam(ep->Ety) || 2388 2391 ((tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) && ep->Enumbytes <= intsize && ep->Enumbytes != 3 && ep->Enumbytes) 2389 2392 ) 2390 2393 ) 2391 2394 { 2392 2395 c = cat(c,params(ep,stackalign)); 2393 2396 goto Lret; 2394 2397 } 2395 2398 // preg is the register to put the parameter ep in 2396 2399 keepmsk = mask[preg]; // don't change preg when evaluating func address 2397 re tregs = keepmsk;2400 regm_t retregs = keepmsk; 2398 2401 if (ep->Eoper == OPstrthis) 2399 2402 { code *c2; 2400 2403 2401 2404 code *c1 = getregs(retregs); 2402 2405 // LEA preg,np[ESP] 2403 2406 unsigned np = stackpush - ep->EV.Vuns; // stack delta to parameter 2404 2407 c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregrm(2,preg,4),FLconst,np); 2405 2408 if (I64) 2406 2409 code_orrex(c2, REX_W); 2407 2410 c = cat3(c,c1,c2); 2408 2411 } 2409 2412 else 2410 2413 { code *cp = codelem(ep,&retregs,FALSE); 2411 2414 c = cat(c,cp); 2412 2415 } 2413 2416 goto Lret; 2414 } 2415 } 2416 c = cat(c, params(e->E2,stackalign)); // push parameters 2417 } 2418 default: 2419 Ldefault2: 2420 c = cat(c, params(e->E2,stackalign)); // push parameters 2421 break; 2422 } 2423 } 2424 else 2425 { assert(I64); 2426 2427 struct Parameter { elem *e; int reg; }; 2428 2429 #ifdef DEBUG 2430 #define PARAMETERS_DIM 3 2431 #else 2432 #define PARAMETERS_DIM 10 2433 #endif 2434 Parameter parameters_tmp[PARAMETERS_DIM]; 2435 Parameter *parameters = parameters_tmp; 2436 size_t parameters_dim = PARAMETERS_DIM; 2437 2438 // Load up parameters[] 2439 elem *ep; 2440 elem *en; 2441 int np = 0; 2442 for (ep = e->E2; ep->Eoper == OPparam; ep = en) 2443 { 2444 if (np + 1 == parameters_dim) // if not space for 2 more 2445 { // Grow parameters[] 2446 parameters_dim = np + 16; 2447 Parameter *p = (Parameter *)alloca(parameters_dim * sizeof(Parameter)); 2448 parameters = (Parameter *)memcpy(p, parameters, np * sizeof(Parameter)); 2449 } 2450 parameters[np++].e = ep->E1; 2451 en = ep->E2; 2452 freenode(ep); 2453 } 2454 parameters[np++].e = ep; 2455 2456 unsigned stackalign = REGSIZE; 2457 tym_t tyf = tybasic(e->E1->Ety); 2458 2459 // Compute numpara, the total bytes pushed on the stack 2460 int r = 0; 2461 int xmmcnt = XMM0; 2462 for (int i = np; --i >= 0;) 2463 { 2464 static const unsigned char argregs[6] = { DI,SI,DX,CX,R8,R9 }; 2465 elem *ep = parameters[i].e; 2466 tym_t ty = ep->Ety; 2467 if (r < sizeof(argregs)/sizeof(argregs[0])) // if more arg regs 2468 { 2469 if ( 2470 // This must match type_jparam() 2471 ty64reg(ty) || 2472 ((tybasic(ty) == TYstruct || tybasic(ty) == TYarray) && 2473 ep->Enumbytes <= REGSIZE && ep->Enumbytes != 3 && ep->Enumbytes) 2474 ) 2475 { 2476 parameters[i].reg = argregs[r]; 2477 r++; 2478 continue; // goes in register, not stack 2479 } 2480 } 2481 else if (xmmcnt < XMM7) 2482 { 2483 if (tyfloating(ty) && tysize(ty) <= 8) 2484 { 2485 parameters[i].reg = xmmcnt; 2486 xmmcnt++; 2487 continue; // goes in register, not stack 2488 } 2489 } 2490 parameters[i].reg = -1; // -1 means no register 2491 numpara += paramsize(ep,stackalign); 2492 } 2493 assert((numpara & (REGSIZE - 1)) == 0); 2494 assert((stackpush & (REGSIZE - 1)) == 0); 2495 2496 /* Adjust start of the stack so after all args are pushed, 2497 * the stack will be aligned. 2498 */ 2499 if (STACKALIGN == 16 && (numpara + stackpush) & (STACKALIGN - 1)) 2500 { 2501 numalign = STACKALIGN - ((numpara + stackpush) & (STACKALIGN - 1)); 2502 c = genc2(NULL,0x81,(REX_W << 16) | modregrm(3,5,SP),numalign); // SUB ESP,numalign 2503 c = genadjesp(c, numalign); 2504 stackpush += numalign; 2505 stackpushsave += numalign; 2506 } 2507 2508 /* Parameters go into the registers RDI,RSI,RDX,RCX,R8,R9 2509 * float and double parameters go into XMM0..XMM7 2510 * For variadic functions, count of XMM registers used goes in AL 2511 */ 2512 for (int i = 0; i < np; i++) 2513 { 2514 elem *ep = parameters[i].e; 2515 int preg = parameters[i].reg; 2516 if (preg == -1) 2517 c = cat(c,params(ep,stackalign)); 2518 else 2519 { 2520 // Goes in register preg, not stack 2521 regm_t retregs = mask[preg]; 2522 if (ep->Eoper == OPstrthis) 2523 { 2524 code *c1 = getregs(retregs); 2525 // LEA preg,np[ESP] 2526 unsigned np = stackpush - ep->EV.Vuns; // stack delta to parameter 2527 code *c2 = genc1(CNIL,0x8D,(REX_W << 16) | 2528 (modregrm(0,4,SP) << 8) | 2529 modregxrm(2,preg,4), FLconst,np); 2530 c = cat3(c,c1,c2); 2531 } 2532 else 2533 { code *cp = scodelem(ep,&retregs,keepmsk,FALSE); 2534 c = cat(c,cp); 2535 } 2536 keepmsk |= retregs; // don't change preg when evaluating func address 2537 } 2538 } 2539 if (e->Eflags & EFLAGS_variadic) 2540 { movregconst(c,AX,xmmcnt - XMM0,1); 2541 keepmsk |= mAX; 2542 } 2543 } 2417 2544 } 2418 2545 else 2419 2546 { 2420 2547 /* Adjust start of the stack so 2421 2548 * the stack will be aligned. 2422 2549 */ 2423 2550 if (STACKALIGN == 16 && (stackpush) & (STACKALIGN - 1)) 2424 2551 { 2425 2552 numalign = STACKALIGN - ((stackpush) & (STACKALIGN - 1)); 2426 2553 c = genc2(NULL,0x81,modregrm(3,5,SP),numalign); // SUB ESP,numalign 2427 2554 if (I64) 2428 2555 code_orrex(c, REX_W); 2429 2556 c = genadjesp(c, numalign); 2430 2557 stackpush += numalign; 2431 2558 stackpushsave += numalign; 2432 2559 } 2433 2560 2434 2561 } 2435 2562 Lret: 2436 2563 cgstate.stackclean--; 2437 if (!I16) 2564 if (I16) 2565 numpara = stackpush - stackpushsave; 2566 else 2438 2567 { 2439 2568 if (numpara != stackpush - stackpushsave) 2440 2569 printf("numpara = %d, stackpush = %d, stackpushsave = %d\n", numpara, stackpush, stackpushsave); 2441 2570 assert(numpara == stackpush - stackpushsave); 2442 2571 } 2443 else2444 numpara = stackpush - stackpushsave;2445 2572 return cat(c,funccall(e,numpara,numalign,pretregs,keepmsk)); 2446 2573 } 2447 2574 2448 2575 /*********************************** 2449 2576 */ 2450 2577 2451 2578 code *cdstrthis(elem *e,regm_t *pretregs) 2452 2579 { 2453 2580 code *c1; 2454 2581 code *c2; 2455 2582 2456 2583 assert(tysize(e->Ety) == REGSIZE); 2457 2584 unsigned reg = findreg(*pretregs & allregs); 2458 2585 c1 = getregs(mask[reg]); 2459 2586 // LEA reg,np[ESP] 2460 2587 unsigned np = stackpush - e->EV.Vuns; // stack delta to parameter 2461 2588 c2 = genc1(CNIL,0x8D,(modregrm(0,4,SP) << 8) | modregxrm(2,reg,4),FLconst,np); 2462 2589 if (I64) 2463 2590 code_orrex(c2, REX_W); 2464 2591 return cat3(c1,c2,fixresult(e,mask[reg],pretregs)); trunk/src/backend/cod2.c
r577 r579 3720 3720 fl = FLcsdata; 3721 3721 c = gen2(c,0x8C, /* MOV mreg,SEG REGISTER */ 3722 3722 modregrm(3,segfl[fl],mreg)); 3723 3723 } 3724 3724 if (*pretregs & mES) 3725 3725 gen2(c,0x8E,modregrm(3,0,mreg)); /* MOV ES,mreg */ 3726 3726 } 3727 3727 return cat(c,getoffset(e,lreg)); 3728 3728 } 3729 3729 3730 3730 /********************************* 3731 3731 * Load the offset portion of the address represented by e into 3732 3732 * reg. 3733 3733 */ 3734 3734 3735 3735 code *getoffset(elem *e,unsigned reg) 3736 3736 { code cs; 3737 3737 code *c; 3738 3738 3739 3739 cs.Iflags = 0; 3740 unsigned char rex = I64 ? REX_W :0;3740 unsigned char rex = 0; 3741 3741 cs.Irex = rex; 3742 3742 assert(e->Eoper == OPvar || e->Eoper == OPrelconst); 3743 3743 enum FL fl = el_fl(e); 3744 3744 switch (fl) 3745 3745 { 3746 3746 case FLdatseg: 3747 3747 cs.IEV2._EP.Vpointer = e->EV.Vpointer; 3748 3748 goto L3; 3749 3749 3750 3750 case FLfardata: 3751 3751 assert(!TARGET_FLAT); 3752 3752 goto L4; 3753 3753 3754 3754 case FLtlsdata: 3755 3755 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 3756 3756 { /* Generate: 3757 3757 * MOV reg,GS:[00000000] 3758 3758 * ADD reg, offset s@TLS_LE 3759 3759 * for locals, and for globals: 3760 3760 * MOV reg,GS:[00000000] trunk/src/backend/cod3.c
r577 r579 1159 1159 { p[0] = len; 1160 1160 memcpy(p + 1,name,len); 1161 1161 len++; 1162 1162 } 1163 1163 return len; 1164 1164 } 1165 1165 #endif 1166 1166 1167 1167 /******************************* 1168 1168 * Generate code for a function start. 1169 1169 * Input: 1170 1170 * Coffset address of start of code 1171 1171 * Output: 1172 1172 * Coffset adjusted for size of code generated 1173 1173 * EBPtoESP 1174 1174 * hasframe 1175 1175 * BPoff 1176 1176 */ 1177 1177 1178 1178 code *prolog() 1179 { code *c;1179 { 1180 1180 SYMIDX si; 1181 1181 unsigned reg; 1182 regm_t topush;1183 tym_t tym;1184 tym_t tyf;1185 1182 char enter; 1186 char pushds;1187 unsigned farfunc;1188 1183 unsigned Foffset; 1189 1184 unsigned xlocalsize; // amount to subtract from ESP to make room for locals 1190 int pushalloc;1191 1185 unsigned pushallocreg; 1192 1186 char guessneedframe; 1193 1187 1194 1188 //printf("cod3.prolog(), needframe = %d, Aalign = %d\n", needframe, Aalign); 1195 1189 debugx(debugw && printf("funcstart()\n")); 1196 1190 regcon.immed.mval = 0; /* no values in registers yet */ 1197 1191 EBPtoESP = -REGSIZE; 1198 1192 hasframe = 0; 1199 pushds = 0;1193 char pushds = 0; 1200 1194 BPoff = 0; 1201 c = CNIL;1202 pushalloc = 0;1203 ty f = funcsym_p->ty();1204 tym = tybasic(tyf);1205 farfunc = tyfarfunc(tym);1195 code *c = CNIL; 1196 int pushalloc = 0; 1197 tym_t tyf = funcsym_p->ty(); 1198 tym_t tym = tybasic(tyf); 1199 unsigned farfunc = tyfarfunc(tym); 1206 1200 pushallocreg = (tyf == TYmfunc) ? CX : AX; 1207 1201 if (config.flags & CFGalwaysframe || funcsym_p->Sfunc->Fflags3 & Ffakeeh) 1208 1202 needframe = 1; 1209 1203 1210 1204 Lagain: 1211 1205 guessneedframe = needframe; 1212 1206 // if (needframe && config.exe & (EX_LINUX | EX_FREEBSD | EX_SOLARIS) && !(usednteh & ~NTEHjmonitor)) 1213 1207 // usednteh |= NTEHpassthru; 1214 1208 1215 1209 /* Compute BP offsets for variables on stack. 1216 1210 * The organization is: 1217 1211 * Poff parameters 1218 1212 * seg of return addr (if far function) 1219 1213 * IP of return addr 1220 1214 * BP-> caller's BP 1221 1215 * DS (if Windows prolog/epilog) 1222 1216 * exception handling context symbol 1223 1217 * Aoff autos and regs 1224 1218 * Foff floating register 1225 1219 * AAoff alloca temporary … … 1251 1245 1252 1246 if (Aalign > REGSIZE) 1253 1247 { 1254 1248 // Adjust Aoff so that it is Aalign byte aligned, assuming that 1255 1249 // before function parameters were pushed the stack was 1256 1250 // Aalign byte aligned 1257 1251 int sz = Poffset + -Aoff + Poff + (needframe ? 0 : REGSIZE); 1258 1252 if (sz & (Aalign - 1)) 1259 1253 Aoff -= sz - (sz & (Aalign - 1)); 1260 1254 } 1261 1255 1262 1256 Foffset = floatreg ? DOUBLESIZE : 0; 1263 1257 Foff = Aoff - align(0,Foffset); 1264 1258 assert(usedalloca != 1); 1265 1259 AAoff = usedalloca ? (Foff - REGSIZE) : Foff; 1266 1260 CSoff = AAoff - align(0,cstop * REGSIZE); 1267 1261 NDPoff = CSoff - align(0,NDP::savetop * NDPSAVESIZE); 1268 1262 Toff = NDPoff - align(0,Toffset); 1269 1263 localsize = -Toff; 1270 1264 1271 topush = fregsaved & ~mfuncreg; // mask of registers that need saving1265 regm_t topush = fregsaved & ~mfuncreg; // mask of registers that need saving 1272 1266 int npush = 0; // number of registers that need saving 1273 1267 for (regm_t x = topush; x; x >>= 1) 1274 1268 npush += x & 1; 1275 1269 1276 1270 // Keep the stack aligned by 8 for any subsequent function calls 1277 1271 if (!I16 && calledafunc && 1278 1272 (STACKALIGN == 16 || config.flags4 & CFG4stackalign)) 1279 1273 { 1280 1274 //printf("npush = %d Poff = x%x needframe = %d localsize = x%x\n", npush, Poff, needframe, localsize); 1281 1275 1282 1276 int sz = Poff + (needframe ? 0 : -REGSIZE) + localsize + npush * REGSIZE; 1283 1277 if (STACKALIGN == 16) 1284 1278 { 1285 1279 if (sz & (8|4)) 1286 1280 localsize += STACKALIGN - (sz & (8|4)); 1287 1281 } 1288 1282 else if (sz & 4) 1289 1283 localsize += 4; 1290 1284 } 1291 1285 … … 1333 1327 farfunc || 1334 1328 config.flags & CFGstack || 1335 1329 xlocalsize >= 0x1000 || 1336 1330 (usednteh & ~NTEHjmonitor) || 1337 1331 anyiasm || 1338 1332 usedalloca 1339 1333 ) 1340 1334 needframe = 1; 1341 1335 } 1342 1336 if (refparam && (anyiasm || I16)) 1343 1337 needframe = 1; 1344 1338 } 1345 1339 1346 1340 if (needframe) 1347 1341 { assert(mfuncreg & mBP); // shouldn't have used mBP 1348 1342 1349 1343 if (!guessneedframe) // if guessed wrong 1350 1344 goto Lagain; 1351 1345 } 1352 1346 1353 #if SIXTEENBIT 1354 if (config.wflags & WFwindows && farfunc) 1347 if (I16 && config.wflags & WFwindows && farfunc) 1355 1348 { int wflags; 1356 1349 int segreg; 1357 1350 1351 #if SCPP 1358 1352 // alloca() can't be because the 'special' parameter won't be at 1359 1353 // a known offset from BP. 1360 1354 if (usedalloca == 1) 1361 1355 synerr(EM_alloca_win); // alloca() can't be in Windows functions 1356 #endif 1362 1357 1363 1358 wflags = config.wflags; 1364 1359 if (wflags & WFreduced && !(tyf & mTYexport)) 1365 1360 { // reduced prolog/epilog for non-exported functions 1366 1361 wflags &= ~(WFdgroup | WFds | WFss); 1367 1362 } 1368 1363 1369 1364 c = getregs(mAX); 1370 1365 assert(!c); /* should not have any value in AX */ 1371 1366 1372 1367 switch (wflags & (WFdgroup | WFds | WFss)) 1373 1368 { case WFdgroup: // MOV AX,DGROUP 1374 1369 if (wflags & WFreduced) 1375 1370 tyf &= ~mTYloadds; // remove redundancy 1376 1371 c = genc(c,0xC7,modregrm(3,0,AX),0,0,FLdatseg,(targ_uns) 0); 1377 1372 c->Iflags ^= CFseg | CFoff; // turn off CFoff, on CFseg 1378 1373 break; 1379 1374 case WFss: 1380 1375 segreg = 2; // SS 1381 1376 goto Lmovax; … … 1393 1388 printf("config.wflags = x%x\n",config.wflags); 1394 1389 #endif 1395 1390 assert(0); 1396 1391 } 1397 1392 if (wflags & WFincbp) 1398 1393 c = gen1(c,0x40 + BP); // INC BP 1399 1394 c = gen1(c,0x50 + BP); // PUSH BP 1400 1395 genregs(c,0x8B,BP,SP); // MOV BP,SP 1401 1396 if (wflags & (WFsaveds | WFds | WFss | WFdgroup)) 1402 1397 { gen1(c,0x1E); // PUSH DS 1403 1398 pushds = TRUE; 1404 1399 BPoff = -REGSIZE; 1405 1400 } 1406 1401 if (wflags & (WFds | WFss | WFdgroup)) 1407 1402 gen2(c,0x8E,modregrm(3,3,AX)); // MOV DS,AX 1408 1403 1409 1404 enter = FALSE; /* don't use ENTER instruction */ 1410 1405 hasframe = 1; /* we have a stack frame */ 1411 1406 } 1412 1407 else 1413 #endif1414 1408 if (needframe) // if variables or parameters 1415 1409 { 1416 1410 if (config.wflags & WFincbp && farfunc) 1417 1411 c = gen1(c,0x40 + BP); /* INC BP */ 1418 1412 if (config.target_cpu < TARGET_80286 || 1419 1413 config.exe & (EX_LINUX | EX_LINUX64 | EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | EX_SOLARIS | EX_SOLARIS64) || 1420 1414 !localsize || 1421 1415 config.flags & CFGstack || 1422 1416 (xlocalsize >= 0x1000 && config.exe & EX_flat) || 1423 1417 localsize >= 0x10000 || 1424 1418 #if NTEXCEPTIONS == 2 1425 1419 (usednteh & ~NTEHjmonitor && (config.flags2 & CFG2seh)) || 1426 1420 #endif 1427 1421 (config.target_cpu >= TARGET_80386 && 1428 1422 config.flags4 & CFG4speed) 1429 1423 ) 1430 1424 { 1431 1425 c = gen1(c,0x50 + BP); // PUSH BP 1432 1426 genregs(c,0x8B,BP,SP); // MOV BP,SP 1433 1427 if (I64) … … 1647 1641 } 1648 1642 1649 1643 #if MARS 1650 1644 if (usednteh & NTEHjmonitor) 1651 1645 { Symbol *sthis; 1652 1646 1653 1647 for (si = 0; 1; si++) 1654 1648 { assert(si < globsym.top); 1655 1649 sthis = globsym.tab[si]; 1656 1650 if (strcmp(sthis->Sident,"this") == 0) 1657 1651 break; 1658 1652 } 1659 1653 c = cat(c,nteh_monitor_prolog(sthis)); 1660 1654 EBPtoESP += 3 * 4; 1661 1655 } 1662 1656 #endif 1663 1657 1664 1658 while (topush) /* while registers to push */ 1665 1659 { reg = findreg(topush); 1666 1660 topush &= ~mask[reg]; 1667 c = gen1(c,0x50 + reg); 1661 c = gen1(c,0x50 + (reg & 7)); 1662 if (reg & 8) 1663 code_orrex(c, REX_B); 1668 1664 EBPtoESP += REGSIZE; 1669 1665 #if ELFOBJ || MACHOBJ 1670 1666 if (config.fulltypes) 1671 1667 { // Emit debug_frame data giving location of saved register 1672 1668 // relative to 0[EBP] 1673 1669 pinholeopt(c, NULL); 1674 1670 dwarf_CFA_set_loc(calcblksize(c)); // address after PUSH reg 1675 1671 dwarf_CFA_offset(reg, -EBPtoESP - REGSIZE); 1676 1672 } 1677 1673 #endif 1678 1674 } 1679 1675 1680 1676 Lcont: 1681 1677 1682 1678 /* Determine if we need to reload DS */ 1683 1679 if (tyf & mTYloadds) 1684 1680 { code *c1; 1685 1681 1686 1682 if (!pushds) // if not already pushed 1687 1683 c = gen1(c,0x1E); // PUSH DS … … 1900 1896 if (tyf & mTYloadds) 1901 1897 { cpopds = gen1(cpopds,0x1F); // POP DS 1902 1898 c = cat(c,cpopds); 1903 1899 spoff += intsize; 1904 1900 } 1905 1901 1906 1902 /* Pop all the general purpose registers saved on the stack 1907 1903 * by the prolog code. Remember to do them in the reverse 1908 1904 * order they were pushed. 1909 1905 */ 1910 1906 reg = I64 ? R15 : DI; 1911 1907 regm = 1 << reg; 1912 1908 topop = fregsaved & ~mfuncreg; 1913 1909 #ifdef DEBUG 1914 1910 if (topop & ~0xFFFF) 1915 1911 printf("fregsaved = x%x, mfuncreg = x%x\n",fregsaved,mfuncreg); 1916 1912 #endif 1917 1913 assert(!(topop & ~0xFFFF)); 1918 1914 while (topop) 1919 1915 { if (topop & regm) 1920 { c = gen1(c,0x58 + reg); // POP reg1916 { c = gen1(c,0x58 + (reg & 7)); // POP reg 1921 1917 if (reg & 8) 1922 1918 code_orrex(c, REX_B); 1923 1919 topop &= ~regm; 1924 1920 spoff += intsize; 1925 1921 } 1926 1922 regm >>= 1; 1927 1923 reg--; 1928 1924 } 1929 1925 1930 1926 #if MARS 1931 1927 if (usednteh & NTEHjmonitor) 1932 1928 { 1933 1929 regm_t retregs = 0; 1934 1930 if (b->BC == BCretexp) 1935 1931 retregs = regmask(b->Belem->Ety, tym); 1936 1932 code *cn = nteh_monitor_epilog(retregs); 1937 1933 c = cat(c,cn); 1938 1934 xlocalsize += 8; 1939 1935 } 1940 1936 #endif … … 4342 4338 #ifdef DEBUG 4343 4339 assert(uev->Vblock->Boffset > OFFSET() || c != 0x7F); 4344 4340 #endif 4345 4341 break; 4346 4342 default: 4347 4343 #ifdef DEBUG 4348 4344 fprintf(stderr,"fl = %d\n",fl); 4349 4345 #endif 4350 4346 assert(0); 4351 4347 } 4352 4348 GEN(c); 4353 4349 } 4354 4350 4355 4351 4356 4352 /**************************** 4357 4353 * Add to the fix list. 4358 4354 */ 4359 4355 4360 4356 void addtofixlist(symbol *s,targ_size_t soffset,int seg,targ_size_t val,int flags) 4361 4357 { fixlist *ln; 4362 static char zeros[ 6];4358 static char zeros[8]; 4363 4359 int numbytes; 4364 4360 4365 4361 //printf("addtofixlist(%p '%s')\n",s,s->Sident); 4366 4362 assert(flags); 4367 4363 ln = (fixlist *) mem_calloc(sizeof(fixlist)); 4368 4364 ln->Lsymbol = s; 4369 4365 ln->Loffset = soffset; 4370 4366 ln->Lseg = seg; 4371 4367 ln->Lflags = flags; 4372 4368 ln->Lval = val; 4373 4369 #if TARGET_OSX 4374 4370 ln->Lfuncsym = funcsym_p; 4375 4371 #endif 4376 4372 ln->Lnext = fixlist::start; 4377 4373 fixlist::start = ln; 4378 4374 #if TARGET_FLAT 4379 4375 numbytes = tysize[TYnptr]; 4380 4376 assert(!(flags & CFseg)); 4381 4377 #else 4382 4378 switch (flags & (CFoff | CFseg)) … … 4880 4876 { printf(" linnum = %d\n",c->IEV2.Vsrcpos.Slinnum); 4881 4877 return; 4882 4878 } 4883 4879 printf(" ESCAPE %d",c->Iop2); 4884 4880 } 4885 4881 if (c->Iflags) 4886 4882 printf(" flg=%x",c->Iflags); 4887 4883 if (ins & M) 4888 4884 { rm = c->Irm; 4889 4885 printf(" rm=%02x=%d,%d,%d",rm,(rm>>6)&3,(rm>>3)&7,rm&7); 4890 4886 if (I32 && issib(rm)) 4891 4887 { unsigned char sib = c->Isib; 4892 4888 printf(" sib=%02x=%d,%d,%d",sib,(sib>>6)&3,(sib>>3)&7,sib&7); 4893 4889 } 4894 4890 if ((rm & 0xC7) == BPRM || (rm & 0xC0) == 0x80 || (rm & 0xC0) == 0x40) 4895 4891 { 4896 4892 switch (c->IFL1) 4897 4893 { 4898 4894 case FLconst: 4899 4895 case FLoffset: 4900 printf(" int = %4 ld",c->IEV1.Vuns);4896 printf(" int = %4d",c->IEV1.Vuns); 4901 4897 break; 4902 4898 case FLblock: 4903 4899 printf(" block = %p",c->IEV1.Vblock); 4904 4900 break; 4905 4901 case FLswitch: 4906 4902 case FLblockoff: 4907 4903 case FLlocalsize: 4908 4904 case FLframehandler: 4909 4905 case 0: 4910 4906 break; 4911 4907 case FLdatseg: 4912 4908 printf(" %d.%lx",c->IEVseg1,c->IEVpointer1); 4913 4909 break; 4914 4910 case FLauto: 4915 4911 case FLreg: 4916 4912 case FLdata: 4917 4913 case FLudata: 4918 4914 case FLpara: 4919 4915 case FLtmp: 4920 4916 case FLbprel: 4921 4917 case FLtlsdata: 4922 4918 printf(" sym='%s'",c->IEVsym1->Sident); 4923 4919 break; 4924 4920 default: 4925 4921 WRFL((enum FL)c->IFL1); 4926 4922 break; 4927 4923 } 4928 4924 } 4929 4925 } 4930 4926 if (ins & T) 4931 4927 { printf(" "); WRFL((enum FL)c->IFL2); 4932 4928 switch (c->IFL2) 4933 4929 { 4934 4930 case FLconst: 4935 printf(" int = %4 ld",c->IEV2.Vuns);4931 printf(" int = %4d",c->IEV2.Vuns); 4936 4932 break; 4937 4933 case FLblock: 4938 4934 printf(" block = %p",c->IEV2.Vblock); 4939 4935 break; 4940 4936 case FLswitch: 4941 4937 case FLblockoff: 4942 4938 case 0: 4943 4939 case FLlocalsize: 4944 4940 case FLframehandler: 4945 4941 break; 4946 4942 case FLdatseg: 4947 4943 printf(" %d.%lx",c->IEVseg2,c->IEVpointer2); 4948 4944 break; 4949 4945 case FLauto: 4950 4946 case FLreg: 4951 4947 case FLpara: 4952 4948 case FLtmp: 4953 4949 case FLbprel: 4954 4950 case FLfunc: 4955 4951 case FLdata: trunk/src/backend/elfobj.c
r572 r579 2701 2701 offset = (foffset + 31) & ~31; 2702 2702 break; 2703 2703 default: 2704 2704 dbg_printf("size was %d\n",(int)size); 2705 2705 assert(0); 2706 2706 break; 2707 2707 } 2708 2708 if (offset > foffset) 2709 2709 fobjbuf->writezeros(offset - foffset); 2710 2710 return offset; 2711 2711 } 2712 2712 2713 2713 /*************************************** 2714 2714 * Stuff pointer to ModuleInfo in its own segment. 2715 2715 */ 2716 2716 2717 2717 #if MARS 2718 2718 2719 2719 void obj_moduleinfo(Symbol *scc) 2720 2720 { 2721 // if (I64) return; // for now, until Phobos64 works 2722 2721 2723 int codeOffset, refOffset; 2722 2724 2723 2725 /* Put in the ModuleReference. */ 2724 2726 { 2725 2727 /* struct ModuleReference 2726 2728 * { 2727 2729 * void* next; 2728 2730 * ModuleReference* module; 2729 2731 * } 2730 2732 */ 2731 2733 const int seg = DATA; 2732 2734 alignOffset(seg, NPTRSIZE); 2733 2735 SegData[seg]->SDoffset = SegData[seg]->SDbuf->size(); 2734 2736 refOffset = SegData[seg]->SDoffset; 2735 2737 SegData[seg]->SDbuf->writezeros(NPTRSIZE); 2736 2738 SegData[seg]->SDoffset += NPTRSIZE; 2737 SegData[seg]->SDoffset += reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFoff); 2738 alignOffset(seg, NPTRSIZE); 2739 SegData[seg]->SDoffset += reftoident(seg, SegData[seg]->SDoffset, scc, 0, CFoffset64 | CFoff); 2739 2740 } 2740 2741 2741 2742 /* Constructor that links the ModuleReference to the head of 2742 2743 * the list pointed to by _Dmoduleref 2743 2744 */ 2744 2745 { 2745 2746 /* ret 2746 2747 * codeOffset: 2747 2748 * pushad 2748 2749 * mov EAX,&ModuleReference 2749 2750 * mov ECX,_DmoduleRef 2750 2751 * mov EDX,[ECX] 2751 2752 * mov [EAX],EDX 2752 2753 * mov [ECX],EAX 2753 2754 * popad 2754 2755 * ret 2755 2756 */ 2756 2757 2757 2758 const int reltype = I64 ? R_X86_64_32 : RI_TYPE_SYM32; 2758 2759 const int refsize = 4; // use 32 bit relocations, even in 64 bit mode 2759 2760 2760 2761 const int seg = CODE; 2761 2762 Outbuffer *buf = SegData[seg]->SDbuf; 2762 2763 SegData[seg]->SDoffset = buf->size(); 2763 2764 codeOffset = SegData[seg]->SDoffset + 1; 2764 2765 buf->writeByte(0xC3); /* ret */ 2765 2766 2766 buf->writeByte(0x60); /* pushad */ 2767 int off = 0; 2768 if (I32) 2769 { buf->writeByte(0x60); // PUSHAD 2770 off = 1; 2771 } 2767 2772 2768 2773 /* movl ModuleReference*, %eax */ 2769 2774 buf->writeByte(0xB8); 2770 2775 buf->write32(refOffset); 2771 elf_addrel(seg, codeOffset + 2, reltype, STI_DATA, 0);2776 elf_addrel(seg, codeOffset + off + 1, reltype, STI_DATA, 0); 2772 2777 2773 2778 /* movl _Dmodule_ref, %ecx */ 2774 2779 buf->writeByte(0xB9); 2775 2780 buf->write32(0); 2776 elf_addrel(seg, codeOffset + 7, reltype, objextern("_Dmodule_ref"), 0);2781 elf_addrel(seg, codeOffset + off + 6, reltype, objextern("_Dmodule_ref"), 0); 2777 2782 2778 2783 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2779 2784 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2780 2785 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2781 2786 2782 buf->writeByte(0x61); /* popad */2787 if (I32) buf->writeByte(0x61); // POPAD 2783 2788 buf->writeByte(0xC3); /* ret */ 2784 2789 SegData[seg]->SDoffset = buf->size(); 2785 2790 } 2786 2791 2787 2792 /* Add reference to constructor into ".ctors" segment 2788 2793 */ 2789 2794 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 2790 2795 2791 2796 Outbuffer *buf = SegData[seg]->SDbuf; 2792 2797 buf->write32(codeOffset); 2793 2798 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 2794 2799 SegData[seg]->SDoffset += NPTRSIZE; 2795 2800 } 2796 2801 2797 2802 #endif 2798 2803 2799 2804 /************************************* 2800 2805 */ 2801 2806 2802 2807 void elfobj_gotref(symbol *s) trunk/src/backend/el.h
r572 r579 26 26 /****************************************** 27 27 * Elems: 28 28 * Elems are the basic tree element. They can be either 29 29 * terminal elems (leaves), unary elems (left subtree exists) 30 30 * or binary elems (left and right subtrees exist). 31 31 */ 32 32 33 33 struct elem 34 34 { 35 35 #ifdef DEBUG 36 36 unsigned short id; 37 37 #define IDelem 0x4C45 // 'EL' 38 38 #define elem_debug(e) assert((e)->id == IDelem) 39 39 #else 40 40 #define elem_debug(e) 41 41 #endif 42 42 43 43 unsigned char Eoper; // operator (OPxxxx) 44 44 unsigned char Ecount; // # of parents of this elem - 1, 45 45 // always 0 until CSE elimination is done 46 unsigned char Eflags; 47 #define EFLAGS_variadic 1 // variadic function call 48 46 49 union eve EV; // variants for each type of elem 47 50 union 48 51 { 49 52 // PARSER 50 53 struct 51 54 { 52 55 struct TYPE *ET_; // pointer to type of elem 53 56 #define ET _EU._EP.ET_ 54 57 55 58 unsigned PEFflags_; 56 59 #define PEFflags _EU._EP.PEFflags_ 57 60 #define PEFnotlvalue 1 // although elem may look like 58 61 // an lvalue, it isn't 59 62 #define PEFtemplate_id 0x10 // symbol is a template-id 60 63 #define PEFparentheses 0x20 // expression was within () 61 64 #define PEFaddrmem 0x40 // address of member 62 65 #define PEFdependent 0x80 // value-dependent 63 66 #define PEFmember 0x100 // was a class member access 64 67 #if !TX86 65 68 #define PEFdblldbl 2 // long double return from dbl func trunk/src/backend/symbol.c
r487 r579 346 346 Symbol *symbol_genauto(elem *e) 347 347 { 348 348 return symbol_genauto(type_fake(e->Ety)); 349 349 } 350 350 351 351 /****************************************** 352 352 * Generate symbol into which we can copy the contents of expression e. 353 353 */ 354 354 355 355 Symbol *symbol_genauto(tym_t ty) 356 356 { 357 357 return symbol_genauto(type_fake(ty)); 358 358 } 359 359 360 360 /**************************************** 361 361 * Add in the variants for a function symbol. 362 362 */ 363 363 364 364 void symbol_func(symbol *s) 365 365 { 366 //printf("symbol_func(%s, x%x)\n", s->Sident, fregsaved); 366 367 symbol_debug(s); 367 368 s->Sfl = FLfunc; 368 369 // Interrupt functions modify all registers 369 370 #if TX86 370 371 // BUG: do interrupt functions really save BP? 371 372 #define mBP 0x20 373 // Note that fregsaved may not be set yet 372 374 s->Sregsaved = (s->Stype && tybasic(s->Stype->Tty) == TYifunc) ? mBP : fregsaved; 373 375 s->Sseg = UNKNOWN; // don't know what segment it is in 374 376 #endif 375 377 if (!s->Sfunc) 376 378 s->Sfunc = func_calloc(); 377 379 } 378 380 379 381 /******************************** 380 382 * Define symbol in specified symbol table. 381 383 * Returns: 382 384 * pointer to symbol 383 385 */ 384 386 385 387 #if SCPP 386 388 387 389 symbol * defsy(const char *p,symbol **parent) 388 390 { 389 391 symbol *s = symbol_calloc(p); 390 392 symbol_addtotree(parent,s); 391 393 return s; trunk/src/backend/ty.h
r557 r579 180 180 #define TYFLref 0x8000 181 181 182 182 /* Groupings of types */ 183 183 184 184 #define tyintegral(ty) (tytab[(ty) & 0xFF] & TYFLintegral) 185 185 186 186 #define tyarithmetic(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLreal | TYFLimaginary | TYFLcomplex)) 187 187 188 188 #define tyaggregate(ty) (tytab[(ty) & 0xFF] & TYFLaggregate) 189 189 190 190 #define tyscalar(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLreal | TYFLimaginary | TYFLcomplex | TYFLptr | TYFLmptr | TYFLnullptr)) 191 191 192 192 #define tyfloating(ty) (tytab[(ty) & 0xFF] & (TYFLreal | TYFLimaginary | TYFLcomplex)) 193 193 194 194 #define tyimaginary(ty) (tytab[(ty) & 0xFF] & TYFLimaginary) 195 195 196 196 #define tycomplex(ty) (tytab[(ty) & 0xFF] & TYFLcomplex) 197 197 198 198 #define tyreal(ty) (tytab[(ty) & 0xFF] & TYFLreal) 199 199 200 // Fits into 64 bit register 201 #define ty64reg(ty) (tytab[(ty) & 0xFF] & (TYFLintegral | TYFLptr)) 202 200 203 #ifndef tyshort 201 204 /* Types that are chars or shorts */ 202 205 #define tyshort(ty) (tytab[(ty) & 0xFF] & TYFLshort) 203 206 #endif 204 207 205 208 /* Detect TYlong or TYulong */ 206 209 #ifndef tylong 207 210 #define tylong(ty) (tybasic(ty) == TYlong || tybasic(ty) == TYulong) 208 211 #endif 209 212 210 213 /* Use to detect a pointer type */ 211 214 #ifndef typtr 212 215 #define typtr(ty) (tytab[(ty) & 0xFF] & TYFLptr) 213 216 #endif 214 217 215 218 /* Use to detect a reference type */ 216 219 #ifndef tyref 217 220 #define tyref(ty) (tytab[(ty) & 0xFF] & TYFLref) 218 221 #endif 219 222 trunk/src/e2ir.c
r569 r579 269 269 ep->Ety = tyret; 270 270 e = ep; 271 271 if (op == OPscale) 272 272 { 273 273 elem *et = e->E1; 274 274 e->E1 = el_una(OPs32_d, TYdouble, e->E2); 275 275 e->E1 = el_una(OPd_ld, TYldouble, e->E1); 276 276 e->E2 = et; 277 277 } 278 278 else if (op == OPyl2x || op == OPyl2xp1) 279 279 { 280 280 elem *et = e->E1; 281 281 e->E1 = e->E2; 282 282 e->E2 = et; 283 283 } 284 284 } 285 285 else 286 286 e = el_una(op,tyret,ep); 287 287 } 288 288 else if (ep) 289 /* Do not do "no side effect" calls if a hidden parameter is passed,289 { /* Do not do "no side effect" calls if a hidden parameter is passed, 290 290 * as the return value is stored through the hidden parameter, which 291 291 * is a side effect. 292 292 */ 293 293 e = el_bin((tf->ispure && tf->isnothrow && (retmethod != RETstack)) ? 294 294 OPcallns : OPcall,tyret,ec,ep); 295 if (tf->varargs) 296 e->Eflags |= EFLAGS_variadic; 297 } 295 298 else 296 e = el_una((tf->ispure && tf->isnothrow && (retmethod != RETstack)) ?299 { e = el_una((tf->ispure && tf->isnothrow && (retmethod != RETstack)) ? 297 300 OPucallns : OPucall,tyret,ec); 301 if (tf->varargs) 302 e->Eflags |= EFLAGS_variadic; 303 } 298 304 299 305 if (retmethod == RETstack) 300 306 { 301 307 e->Ety = TYnptr; 302 308 e = el_una(OPind, tyret, e); 303 309 } 304 310 305 311 #if DMDV2 306 312 if (tf->isref) 307 313 { 308 314 e->Ety = TYnptr; 309 315 e = el_una(OPind, tyret, e); 310 316 } 311 317 #endif 312 318 313 319 if (tybasic(tyret) == TYstruct) 314 320 { 315 321 e->Enumbytes = tret->size(); 316 322 } 317 323 e = el_combine(eside, e); … … 2060 2066 { 2061 2067 elem *ep; 2062 2068 CatExp *ce = this; 2063 2069 int n = 2; 2064 2070 2065 2071 ep = eval_Darray(irs, ce->e2); 2066 2072 do 2067 2073 { 2068 2074 n++; 2069 2075 ce = (CatExp *)ce->e1; 2070 2076 ep = el_param(ep, eval_Darray(irs, ce->e2)); 2071 2077 } while (ce->e1->op == TOKcat); 2072 2078 ep = el_param(ep, eval_Darray(irs, ce->e1)); 2073 2079 #if 1 2074 2080 ep = el_params( 2075 2081 ep, 2076 2082 el_long(TYint, n), 2077 2083 ta->getTypeInfo(NULL)->toElem(irs), 2078 2084 NULL); 2079 2085 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep); 2086 e->Eflags |= EFLAGS_variadic; 2080 2087 #else 2081 2088 ep = el_params( 2082 2089 ep, 2083 2090 el_long(TYint, n), 2084 2091 el_long(TYint, tn->size()), 2085 2092 NULL); 2086 2093 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep); 2094 e->Eflags |= EFLAGS_variadic; 2087 2095 #endif 2088 2096 } 2089 2097 else 2090 2098 { 2091 2099 elem *e1; 2092 2100 elem *e2; 2093 2101 elem *ep; 2094 2102 2095 2103 e1 = eval_Darray(irs, this->e1); 2096 2104 e2 = eval_Darray(irs, this->e2); 2097 2105 #if 1 2098 2106 ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL); 2099 2107 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep); 2100 2108 #else 2101 2109 ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL); 2102 2110 e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep); 2103 2111 #endif 2104 2112 } 2105 2113 el_setLoc(e,loc); 2106 2114 } … … 4545 4553 } 4546 4554 args.data[dim - (i + 1)] = (void *)ep; 4547 4555 } 4548 4556 4549 4557 /* Because the number of parameters can get very large, produce 4550 4558 * a balanced binary tree so we don't blow up the stack in 4551 4559 * the subsequent tree walking code. 4552 4560 */ 4553 4561 e = el_params(args.data, dim + 1); 4554 4562 } 4555 4563 else 4556 4564 { dim = 0; 4557 4565 e = el_long(TYint, 0); 4558 4566 } 4559 4567 Type *tb = type->toBasetype(); 4560 4568 #if 1 4561 4569 e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); 4562 4570 4563 4571 // call _d_arrayliteralT(ti, dim, ...) 4564 4572 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e); 4573 e->Eflags |= EFLAGS_variadic; 4565 4574 #else 4566 4575 e = el_param(e, el_long(TYint, tb->next->size())); 4567 4576 4568 4577 // call _d_arrayliteral(size, dim, ...) 4569 4578 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e); 4579 e->Eflags |= EFLAGS_variadic; 4570 4580 #endif 4571 4581 if (tb->ty == Tarray) 4572 4582 { 4573 4583 e = el_pair(TYullong, el_long(TYint, dim), e); 4574 4584 } 4575 4585 else if (tb->ty == Tpointer) 4576 4586 { 4577 4587 } 4578 4588 else 4579 4589 { 4580 4590 e = el_una(OPind,TYstruct,e); 4581 4591 e->Enumbytes = type->size(); 4582 4592 } 4583 4593 4584 4594 el_setLoc(e,loc); 4585 4595 return e; 4586 4596 } 4587 4597 4588 4598 4589 4599 elem *AssocArrayLiteralExp::toElem(IRState *irs) … … 4619 4629 #if 0 4620 4630 /* Unfortunately, the hash function for Aa (array of chars) is custom and 4621 4631 * different from Axa and Aya, which get the generic hash function. 4622 4632 * So, rewrite the type of the AArray so that if it's key type 4623 4633 * is an array of const or invariant, make it an array of mutable. 4624 4634 */ 4625 4635 Type *tkey = ta->index->toBasetype(); 4626 4636 if (tkey->ty == Tarray) 4627 4637 { 4628 4638 tkey = tkey->nextOf()->mutableOf()->arrayOf(); 4629 4639 tkey = tkey->semantic(0, NULL); 4630 4640 ta = new TypeAArray(ta->nextOf(), tkey); 4631 4641 ta = (TypeAArray *)ta->merge(); 4632 4642 } 4633 4643 #endif 4634 4644 4635 4645 e = el_param(e, ta->getTypeInfo(NULL)->toElem(irs)); 4636 4646 4637 4647 // call _d_assocarrayliteralT(ti, dim, ...) 4638 4648 e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e); 4649 e->Eflags |= EFLAGS_variadic; 4639 4650 4640 4651 el_setLoc(e,loc); 4641 4652 return e; 4642 4653 } 4643 4654 4644 4655 4645 4656 /******************************************* 4646 4657 * Generate elem to zero fill contents of Symbol stmp 4647 4658 * from *poffset..offset2. 4648 4659 * May store anywhere from 0..maxoff, as this function 4649 4660 * tries to use aligned int stores whereever possible. 4650 4661 * Update *poffset to end of initialized hole; *poffset will be >= offset2. 4651 4662 */ 4652 4663 4653 4664 elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff) 4654 4665 { elem *e = NULL; 4655 4666 int basealign = 1; 4656 4667 4657 4668 while (*poffset < offset2) 4658 4669 { tym_t ty; trunk/src/msc.c
r569 r579 23 23 #include "dt.h" 24 24 #include "cgcv.h" 25 25 26 26 static char __file__[] = __FILE__; /* for tassert.h */ 27 27 #include "tassert.h" 28 28 29 29 extern Global global; 30 30 extern int REALSIZE; 31 31 32 32 Config config; 33 33 Configv configv; 34 34 35 35 struct Environment; 36 36 37 37 /************************************** 38 38 * Initialize config variables. 39 39 */ 40 40 41 41 void out_config_init() 42 42 { 43 //printf("out_config_init()\n"); 43 44 Param *params = &global.params; 44 45 45 46 if (!config.target_cpu) 46 47 { config.target_cpu = TARGET_PentiumPro; 47 48 config.target_scheduler = config.target_cpu; 48 49 } 49 50 config.fulltypes = CVNONE; 50 51 config.inline8087 = 1; 51 52 config.memmodel = 0; 52 53 config.flags |= CFGuchar; // make sure TYchar is unsigned 53 54 #if TARGET_WINDOS 54 55 if (params->isX86_64) 55 56 config.exe = EX_WIN64; 56 57 else 57 58 config.exe = EX_NT; 58 59 59 60 // Win32 eh 60 61 config.flags2 |= CFG2seh; 61 62 62 63 if (params->run)
