Changeset 810
- Timestamp:
- 12/21/10 09:44:03 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod1.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cod2.c (modified) (3 diffs)
- trunk/src/backend/cg87.c (modified) (1 diff)
- trunk/src/backend/cod1.c (modified) (1 diff)
- trunk/src/backend/cod2.c (modified) (3 diffs)
- trunk/src/template.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r805 r810 2000 2000 freenode(e->E1); 2001 2001 c1 = cat3(c1,c2,fixresult87(e,mST0 | mPSW,pretregs)); 2002 2002 return c1; 2003 2003 } 2004 2004 2005 2005 /******************************* 2006 2006 * Perform an assignment to a long double/double/float. 2007 2007 */ 2008 2008 2009 2009 code *complex_eq87(elem *e,regm_t *pretregs) 2010 2010 { 2011 2011 regm_t retregs; 2012 2012 code *c1,*c2; 2013 2013 code cs; 2014 2014 unsigned op1; 2015 2015 unsigned op2; 2016 2016 unsigned sz; 2017 2017 tym_t ty1; 2018 2018 int fxch = 0; 2019 2019 2020 //printf("complex_eq87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 2020 2021 assert(e->Eoper == OPeq); 2021 2022 cs.Iflags = ADDFWAIT() ? CFwait : 0; 2022 2023 cs.Irex = 0; 2023 2024 retregs = mST01 | (*pretregs & mPSW); 2024 2025 c1 = codelem(e->E2,&retregs,FALSE); 2025 2026 ty1 = tybasic(e->E1->Ety); 2026 2027 switch (ty1) 2027 2028 { 2028 2029 case TYcdouble: op1 = ESC(MFdouble,1); op2 = 3; break; 2029 2030 case TYcfloat: op1 = ESC(MFfloat,1); op2 = 3; break; 2030 2031 case TYcldouble: op1 = 0xDB; op2 = 7; break; 2031 2032 default: 2032 2033 assert(0); 2033 2034 } 2034 if (*pretregs & mST01) // if want result on stack too2035 if (*pretregs & (mST01 | mXMM0 | mXMM1)) // if want result on stack too 2035 2036 { 2036 2037 if (ty1 == TYcldouble) 2037 2038 { 2038 2039 c1 = cat(c1,push87()); 2039 2040 c1 = cat(c1,push87()); 2040 2041 c1 = genf2(c1,0xD9,0xC0 + 1); // FLD ST(1) 2041 2042 genf2(c1,0xD9,0xC0 + 1); // FLD ST(1) 2042 2043 pop87(); 2043 2044 pop87(); 2044 2045 } 2045 2046 else 2046 2047 { op2 = 2; // FST e->E1 2047 2048 fxch = 1; 2048 2049 } 2049 2050 } 2050 2051 else 2051 2052 { // FSTP e->E1 2052 2053 pop87(); 2053 2054 pop87(); 2054 2055 } 2055 2056 sz = tysize(ty1) / 2; 2056 if (*pretregs & mST01)2057 if (*pretregs & (mST01 | mXMM0 | mXMM1)) 2057 2058 { 2058 2059 cs.Iflags = 0; 2059 2060 cs.Irex = 0; 2060 2061 cs.Iop = op1; 2061 2062 c2 = getlvalue(&cs, e->E1, 0); 2062 2063 cs.IEVoffset1 += sz; 2063 2064 cs.Irm |= modregrm(0, op2, 0); 2064 2065 c2 = cat(c2, makesure87(e->E2, sz, 0, 0)); 2065 2066 c2 = gen(c2, &cs); 2066 2067 c2 = genfwait(c2); 2067 2068 c2 = cat(c2, makesure87(e->E2, 0, 1, 0)); 2068 2069 } 2069 2070 else 2070 2071 { 2071 2072 c2 = loadea(e->E1,&cs,op1,op2,sz,0,0); 2072 2073 c2 = genfwait(c2); 2073 2074 } 2074 2075 if (fxch) 2075 2076 c2 = genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2076 2077 cs.IEVoffset1 -= sz; branches/dmd-1.x/src/backend/cod1.c
r805 r810 1728 1728 } 1729 1729 } 1730 1730 return c; 1731 1731 } 1732 1732 1733 1733 1734 1734 /***************************** 1735 1735 * Given a result in registers, test it for TRUE or FALSE. 1736 1736 * Will fail if TYfptr and the reg is ES! 1737 1737 * If saveflag is TRUE, preserve the contents of the 1738 1738 * registers. 1739 1739 */ 1740 1740 1741 1741 code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 1742 1742 { 1743 1743 unsigned scrreg; /* scratch register */ 1744 1744 regm_t scrregm; 1745 1745 1746 1746 #ifdef DEBUG 1747 1747 if (!(regm & (mBP | ALLREGS))) 1748 printf("tstresult(regm = x%x, tym = x%x, saveflag = %d)\n",1749 regm ,tym,saveflag);1750 #endif 1751 assert(regm & ( mBP | ALLREGS));1748 printf("tstresult(regm = %s, tym = x%x, saveflag = %d)\n", 1749 regm_str(regm),tym,saveflag); 1750 #endif 1751 assert(regm & (XMMREGS | mBP | ALLREGS)); 1752 1752 tym = tybasic(tym); 1753 1753 code *ce = CNIL; 1754 1754 unsigned reg = findreg(regm); 1755 1755 unsigned sz = tysize[tym]; 1756 1756 if (sz == 1) 1757 1757 { assert(regm & BYTEREGS); 1758 1758 return genregs(ce,0x84,reg,reg); // TEST regL,regL 1759 } 1760 if (regm & XMMREGS) 1761 { 1762 unsigned xreg; 1763 regm_t xregs = XMMREGS & ~regm; 1764 ce = allocreg(&xregs, &xreg, TYdouble); 1765 unsigned op = 0; 1766 if (tym == TYdouble || tym == TYidouble || tym == TYcdouble) 1767 op = 0x660000; 1768 ce = gen2(ce,op | 0x0F57,modregrm(3,xreg-XMM0,xreg-XMM0)); // XORPS xreg,xreg 1769 gen2(ce,op | 0x0F2E,modregrm(3,xreg-XMM0,reg-XMM0)); // UCOMISS xreg,reg 1770 if (tym == TYcfloat || tym == TYcdouble) 1771 { code *cnop = gennop(CNIL); 1772 genjmp(ce,JNE,FLcode,(block *) cnop); // JNE L1 1773 genjmp(ce,JP, FLcode,(block *) cnop); // JP L1 1774 reg = findreg(regm & ~mask[reg]); 1775 gen2(ce,op | 0x0F2E,modregrm(3,xreg-XMM0,reg-XMM0)); // UCOMISS xreg,reg 1776 ce = cat(ce, cnop); 1777 } 1778 return ce; 1759 1779 } 1760 1780 if (sz <= REGSIZE) 1761 1781 { 1762 1782 if (!I16) 1763 1783 { 1764 1784 if (tym == TYfloat) 1765 1785 { if (saveflag) 1766 1786 { 1767 1787 scrregm = allregs & ~regm; /* possible scratch regs */ 1768 1788 ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 1769 1789 ce = genmovreg(ce,scrreg,reg); /* MOV scrreg,msreg */ 1770 1790 reg = scrreg; 1771 1791 } 1772 1792 ce = cat(ce,getregs(mask[reg])); 1773 1793 return gen2(ce,0xD1,modregrmx(3,4,reg)); // SHL reg,1 1774 1794 } 1775 1795 ce = gentstreg(ce,reg); // TEST reg,reg 1776 1796 if (sz == SHORTSIZE) 1777 1797 ce->Iflags |= CFopsize; /* 16 bit operands */ 1778 1798 else if (sz == 8) branches/dmd-1.x/src/backend/cod2.c
r772 r810 200 200 /* Therefore, numwords can never be 2. */ 201 201 assert(!(tyfv(ty1) && tyfv(ty2))); 202 202 if (sz == 2 * REGSIZE) 203 203 { 204 204 numwords++; 205 205 } 206 206 } 207 207 else 208 208 { /* If ty is a TYfptr, but both operands are long, treat the */ 209 209 /* operation as a long. */ 210 210 if ((tylong(ty1) || ty1 == TYhptr) && 211 211 (tylong(ty2) || ty2 == TYhptr)) 212 212 numwords++; 213 213 } 214 214 215 215 // Special cases where only flags are set 216 216 if (test && tysize[ty1] <= REGSIZE && 217 217 (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 218 218 { 219 219 // Handle the case of (var & const) 220 if (e2->Eoper == OPconst )220 if (e2->Eoper == OPconst && el_signx32(e2)) 221 221 { 222 222 c = getlvalue(&cs,e1,0); 223 223 targ_size_t value = e2->EV.Vpointer; 224 224 if (sz == 2) 225 225 value &= 0xFFFF; 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 230 if (sz == 8 && !I64) 231 231 { 232 232 assert(value == (int)value); // sign extend imm32 233 233 } 234 234 op1 = 0xF7; 235 235 cs.IEV2.Vint = value; 236 236 cs.IFL2 = FLconst; 237 237 goto L10; 238 238 } 239 239 240 240 // Handle (exp & reg) … … 278 278 (!I16 && e1->Ecount) 279 279 ) 280 280 { 281 281 int inc = e->Ecount != 0; 282 282 nest += inc; 283 283 c = getlvalue(&cs,e,0); 284 284 nest -= inc; 285 285 unsigned reg; 286 286 c = cat(c,allocreg(pretregs,®,ty)); 287 287 cs.Iop = 0x8D; 288 288 code_newreg(&cs, reg); 289 289 c = gen(c,&cs); // LEA reg,EA 290 290 if (rex) 291 291 code_orrex(c, rex); 292 292 return c; 293 293 } 294 294 295 295 // Handle the case of ((e + c) + e2) 296 296 if (!I16 && 297 297 e1oper == OPadd && 298 (e1->E2->Eoper == OPconst || e2oper == OPconst) && 298 (e1->E2->Eoper == OPconst && el_signx32(e1->E2) || 299 e2oper == OPconst && el_signx32(e2)) && 299 300 !e1->Ecount 300 301 ) 301 302 { elem *e11; 302 303 elem *ebase; 303 304 elem *edisp; 304 305 int ss; 305 306 int ss2; 306 307 unsigned reg1,reg2; 307 308 code *c1,*c2,*c3; 308 309 309 if (e2oper == OPconst )310 if (e2oper == OPconst && el_signx32(e2)) 310 311 { edisp = e2; 311 312 ebase = e1->E2; 312 313 } 313 314 else 314 315 { edisp = e1->E2; 315 316 ebase = e2; 316 317 } 317 318 318 319 e11 = e1->E1; 319 320 retregs = *pretregs & ALLREGS; 320 321 if (!retregs) 321 322 retregs = ALLREGS; 322 323 ss = 0; 323 324 ss2 = 0; 324 325 325 326 // Handle the case of (((e * c1) + c2) + e2) 326 327 // Handle the case of (((e << c1) + c2) + e2) 327 328 if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 328 329 e11->E2->Eoper == OPconst && 329 330 !e11->Ecount … … 611 612 612 613 case OPrelconst: 613 614 if (sz != REGSIZE) 614 615 goto L2; 615 616 if (segfl[el_fl(e2)] != 3) /* if not in data segment */ 616 617 goto L2; 617 618 if (evalinregister(e2)) 618 619 goto L2; 619 620 cs.IEVoffset2 = e2->EV.sp.Voffset; 620 621 cs.IEVsym2 = e2->EV.sp.Vsym; 621 622 cs.Iflags |= CFoff; 622 623 i = 0; /* no INC or DEC opcode */ 623 624 rval = 0; 624 625 goto L3; 625 626 626 627 case OPconst: 627 628 if (tyfv(ty2)) 628 629 goto L2; 629 630 if (numwords == 1) 630 631 { 632 if (!el_signx32(e2)) 633 goto L2; 631 634 i = e2->EV.Vpointer; 632 635 if (word) 633 636 { 634 637 if (!(*pretregs & mPSW) && 635 638 config.flags4 & CFG4speed && 636 639 (e->Eoper == OPor || e->Eoper == OPxor || test || 637 640 (e1->Eoper != OPvar && e1->Eoper != OPind))) 638 641 { word = 0; 639 642 i &= 0xFFFF; 640 643 } 641 644 } 642 645 rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 643 646 cs.IEV2.Vint = i; 644 647 L3: 645 648 op1 ^= byte; 646 649 cs.Iflags |= word; 647 650 if (rval) 648 651 { cs.Iop = op1 ^ 2; 649 652 mode = rreg; 650 653 } trunk/src/backend/cg87.c
r805 r810 2000 2000 freenode(e->E1); 2001 2001 c1 = cat3(c1,c2,fixresult87(e,mST0 | mPSW,pretregs)); 2002 2002 return c1; 2003 2003 } 2004 2004 2005 2005 /******************************* 2006 2006 * Perform an assignment to a long double/double/float. 2007 2007 */ 2008 2008 2009 2009 code *complex_eq87(elem *e,regm_t *pretregs) 2010 2010 { 2011 2011 regm_t retregs; 2012 2012 code *c1,*c2; 2013 2013 code cs; 2014 2014 unsigned op1; 2015 2015 unsigned op2; 2016 2016 unsigned sz; 2017 2017 tym_t ty1; 2018 2018 int fxch = 0; 2019 2019 2020 //printf("complex_eq87(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs)); 2020 2021 assert(e->Eoper == OPeq); 2021 2022 cs.Iflags = ADDFWAIT() ? CFwait : 0; 2022 2023 cs.Irex = 0; 2023 2024 retregs = mST01 | (*pretregs & mPSW); 2024 2025 c1 = codelem(e->E2,&retregs,FALSE); 2025 2026 ty1 = tybasic(e->E1->Ety); 2026 2027 switch (ty1) 2027 2028 { 2028 2029 case TYcdouble: op1 = ESC(MFdouble,1); op2 = 3; break; 2029 2030 case TYcfloat: op1 = ESC(MFfloat,1); op2 = 3; break; 2030 2031 case TYcldouble: op1 = 0xDB; op2 = 7; break; 2031 2032 default: 2032 2033 assert(0); 2033 2034 } 2034 if (*pretregs & mST01) // if want result on stack too2035 if (*pretregs & (mST01 | mXMM0 | mXMM1)) // if want result on stack too 2035 2036 { 2036 2037 if (ty1 == TYcldouble) 2037 2038 { 2038 2039 c1 = cat(c1,push87()); 2039 2040 c1 = cat(c1,push87()); 2040 2041 c1 = genf2(c1,0xD9,0xC0 + 1); // FLD ST(1) 2041 2042 genf2(c1,0xD9,0xC0 + 1); // FLD ST(1) 2042 2043 pop87(); 2043 2044 pop87(); 2044 2045 } 2045 2046 else 2046 2047 { op2 = 2; // FST e->E1 2047 2048 fxch = 1; 2048 2049 } 2049 2050 } 2050 2051 else 2051 2052 { // FSTP e->E1 2052 2053 pop87(); 2053 2054 pop87(); 2054 2055 } 2055 2056 sz = tysize(ty1) / 2; 2056 if (*pretregs & mST01)2057 if (*pretregs & (mST01 | mXMM0 | mXMM1)) 2057 2058 { 2058 2059 cs.Iflags = 0; 2059 2060 cs.Irex = 0; 2060 2061 cs.Iop = op1; 2061 2062 c2 = getlvalue(&cs, e->E1, 0); 2062 2063 cs.IEVoffset1 += sz; 2063 2064 cs.Irm |= modregrm(0, op2, 0); 2064 2065 c2 = cat(c2, makesure87(e->E2, sz, 0, 0)); 2065 2066 c2 = gen(c2, &cs); 2066 2067 c2 = genfwait(c2); 2067 2068 c2 = cat(c2, makesure87(e->E2, 0, 1, 0)); 2068 2069 } 2069 2070 else 2070 2071 { 2071 2072 c2 = loadea(e->E1,&cs,op1,op2,sz,0,0); 2072 2073 c2 = genfwait(c2); 2073 2074 } 2074 2075 if (fxch) 2075 2076 c2 = genf2(c2,0xD9,0xC8 + 1); // FXCH ST(1) 2076 2077 cs.IEVoffset1 -= sz; trunk/src/backend/cod1.c
r805 r810 1728 1728 } 1729 1729 } 1730 1730 return c; 1731 1731 } 1732 1732 1733 1733 1734 1734 /***************************** 1735 1735 * Given a result in registers, test it for TRUE or FALSE. 1736 1736 * Will fail if TYfptr and the reg is ES! 1737 1737 * If saveflag is TRUE, preserve the contents of the 1738 1738 * registers. 1739 1739 */ 1740 1740 1741 1741 code *tstresult(regm_t regm,tym_t tym,unsigned saveflag) 1742 1742 { 1743 1743 unsigned scrreg; /* scratch register */ 1744 1744 regm_t scrregm; 1745 1745 1746 1746 #ifdef DEBUG 1747 1747 if (!(regm & (mBP | ALLREGS))) 1748 printf("tstresult(regm = x%x, tym = x%x, saveflag = %d)\n",1749 regm ,tym,saveflag);1750 #endif 1751 assert(regm & ( mBP | ALLREGS));1748 printf("tstresult(regm = %s, tym = x%x, saveflag = %d)\n", 1749 regm_str(regm),tym,saveflag); 1750 #endif 1751 assert(regm & (XMMREGS | mBP | ALLREGS)); 1752 1752 tym = tybasic(tym); 1753 1753 code *ce = CNIL; 1754 1754 unsigned reg = findreg(regm); 1755 1755 unsigned sz = tysize[tym]; 1756 1756 if (sz == 1) 1757 1757 { assert(regm & BYTEREGS); 1758 1758 return genregs(ce,0x84,reg,reg); // TEST regL,regL 1759 } 1760 if (regm & XMMREGS) 1761 { 1762 unsigned xreg; 1763 regm_t xregs = XMMREGS & ~regm; 1764 ce = allocreg(&xregs, &xreg, TYdouble); 1765 unsigned op = 0; 1766 if (tym == TYdouble || tym == TYidouble || tym == TYcdouble) 1767 op = 0x660000; 1768 ce = gen2(ce,op | 0x0F57,modregrm(3,xreg-XMM0,xreg-XMM0)); // XORPS xreg,xreg 1769 gen2(ce,op | 0x0F2E,modregrm(3,xreg-XMM0,reg-XMM0)); // UCOMISS xreg,reg 1770 if (tym == TYcfloat || tym == TYcdouble) 1771 { code *cnop = gennop(CNIL); 1772 genjmp(ce,JNE,FLcode,(block *) cnop); // JNE L1 1773 genjmp(ce,JP, FLcode,(block *) cnop); // JP L1 1774 reg = findreg(regm & ~mask[reg]); 1775 gen2(ce,op | 0x0F2E,modregrm(3,xreg-XMM0,reg-XMM0)); // UCOMISS xreg,reg 1776 ce = cat(ce, cnop); 1777 } 1778 return ce; 1759 1779 } 1760 1780 if (sz <= REGSIZE) 1761 1781 { 1762 1782 if (!I16) 1763 1783 { 1764 1784 if (tym == TYfloat) 1765 1785 { if (saveflag) 1766 1786 { 1767 1787 scrregm = allregs & ~regm; /* possible scratch regs */ 1768 1788 ce = allocreg(&scrregm,&scrreg,TYoffset); /* allocate scratch reg */ 1769 1789 ce = genmovreg(ce,scrreg,reg); /* MOV scrreg,msreg */ 1770 1790 reg = scrreg; 1771 1791 } 1772 1792 ce = cat(ce,getregs(mask[reg])); 1773 1793 return gen2(ce,0xD1,modregrmx(3,4,reg)); // SHL reg,1 1774 1794 } 1775 1795 ce = gentstreg(ce,reg); // TEST reg,reg 1776 1796 if (sz == SHORTSIZE) 1777 1797 ce->Iflags |= CFopsize; /* 16 bit operands */ 1778 1798 else if (sz == 8) trunk/src/backend/cod2.c
r772 r810 200 200 /* Therefore, numwords can never be 2. */ 201 201 assert(!(tyfv(ty1) && tyfv(ty2))); 202 202 if (sz == 2 * REGSIZE) 203 203 { 204 204 numwords++; 205 205 } 206 206 } 207 207 else 208 208 { /* If ty is a TYfptr, but both operands are long, treat the */ 209 209 /* operation as a long. */ 210 210 if ((tylong(ty1) || ty1 == TYhptr) && 211 211 (tylong(ty2) || ty2 == TYhptr)) 212 212 numwords++; 213 213 } 214 214 215 215 // Special cases where only flags are set 216 216 if (test && tysize[ty1] <= REGSIZE && 217 217 (e1->Eoper == OPvar || (e1->Eoper == OPind && !e1->Ecount))) 218 218 { 219 219 // Handle the case of (var & const) 220 if (e2->Eoper == OPconst )220 if (e2->Eoper == OPconst && el_signx32(e2)) 221 221 { 222 222 c = getlvalue(&cs,e1,0); 223 223 targ_size_t value = e2->EV.Vpointer; 224 224 if (sz == 2) 225 225 value &= 0xFFFF; 226 226 else if (sz == 4) 227 227 value &= 0xFFFFFFFF; 228 228 if (reghasvalue(byte ? BYTEREGS : ALLREGS,value,®)) 229 229 goto L11; 230 230 if (sz == 8 && !I64) 231 231 { 232 232 assert(value == (int)value); // sign extend imm32 233 233 } 234 234 op1 = 0xF7; 235 235 cs.IEV2.Vint = value; 236 236 cs.IFL2 = FLconst; 237 237 goto L10; 238 238 } 239 239 240 240 // Handle (exp & reg) … … 278 278 (!I16 && e1->Ecount) 279 279 ) 280 280 { 281 281 int inc = e->Ecount != 0; 282 282 nest += inc; 283 283 c = getlvalue(&cs,e,0); 284 284 nest -= inc; 285 285 unsigned reg; 286 286 c = cat(c,allocreg(pretregs,®,ty)); 287 287 cs.Iop = 0x8D; 288 288 code_newreg(&cs, reg); 289 289 c = gen(c,&cs); // LEA reg,EA 290 290 if (rex) 291 291 code_orrex(c, rex); 292 292 return c; 293 293 } 294 294 295 295 // Handle the case of ((e + c) + e2) 296 296 if (!I16 && 297 297 e1oper == OPadd && 298 (e1->E2->Eoper == OPconst || e2oper == OPconst) && 298 (e1->E2->Eoper == OPconst && el_signx32(e1->E2) || 299 e2oper == OPconst && el_signx32(e2)) && 299 300 !e1->Ecount 300 301 ) 301 302 { elem *e11; 302 303 elem *ebase; 303 304 elem *edisp; 304 305 int ss; 305 306 int ss2; 306 307 unsigned reg1,reg2; 307 308 code *c1,*c2,*c3; 308 309 309 if (e2oper == OPconst )310 if (e2oper == OPconst && el_signx32(e2)) 310 311 { edisp = e2; 311 312 ebase = e1->E2; 312 313 } 313 314 else 314 315 { edisp = e1->E2; 315 316 ebase = e2; 316 317 } 317 318 318 319 e11 = e1->E1; 319 320 retregs = *pretregs & ALLREGS; 320 321 if (!retregs) 321 322 retregs = ALLREGS; 322 323 ss = 0; 323 324 ss2 = 0; 324 325 325 326 // Handle the case of (((e * c1) + c2) + e2) 326 327 // Handle the case of (((e << c1) + c2) + e2) 327 328 if ((e11->Eoper == OPmul || e11->Eoper == OPshl) && 328 329 e11->E2->Eoper == OPconst && 329 330 !e11->Ecount … … 611 612 612 613 case OPrelconst: 613 614 if (sz != REGSIZE) 614 615 goto L2; 615 616 if (segfl[el_fl(e2)] != 3) /* if not in data segment */ 616 617 goto L2; 617 618 if (evalinregister(e2)) 618 619 goto L2; 619 620 cs.IEVoffset2 = e2->EV.sp.Voffset; 620 621 cs.IEVsym2 = e2->EV.sp.Vsym; 621 622 cs.Iflags |= CFoff; 622 623 i = 0; /* no INC or DEC opcode */ 623 624 rval = 0; 624 625 goto L3; 625 626 626 627 case OPconst: 627 628 if (tyfv(ty2)) 628 629 goto L2; 629 630 if (numwords == 1) 630 631 { 632 if (!el_signx32(e2)) 633 goto L2; 631 634 i = e2->EV.Vpointer; 632 635 if (word) 633 636 { 634 637 if (!(*pretregs & mPSW) && 635 638 config.flags4 & CFG4speed && 636 639 (e->Eoper == OPor || e->Eoper == OPxor || test || 637 640 (e1->Eoper != OPvar && e1->Eoper != OPind))) 638 641 { word = 0; 639 642 i &= 0xFFFF; 640 643 } 641 644 } 642 645 rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 643 646 cs.IEV2.Vint = i; 644 647 L3: 645 648 op1 ^= byte; 646 649 cs.Iflags |= word; 647 650 if (rval) 648 651 { cs.Iop = op1 ^ 2; 649 652 mode = rreg; 650 653 } trunk/src/template.c
r809 r810 1298 1298 } 1299 1299 declareParameter(paramscope, tparam, oded); 1300 1300 dedargs->data[i] = (void *)oded; 1301 1301 } 1302 1302 } 1303 1303 1304 1304 #if DMDV2 1305 1305 if (constraint) 1306 1306 { /* Check to see if constraint is satisfied. 1307 1307 */ 1308 1308 makeParamNamesVisibleInConstraint(paramscope); 1309 1309 Expression *e = constraint->syntaxCopy(); 1310 1310 paramscope->flags |= SCOPEstaticif; 1311 1311 1312 1312 /* Detect recursive attempts to instantiate this template declaration, 1313 1313 * Bugzilla 4072 1314 1314 * void foo(T)(T x) if (is(typeof(foo(x)))) { } 1315 1315 * static assert(!is(typeof(foo(7)))); 1316 1316 * Recursive attempts are regarded as a constraint failure. 1317 1317 */ 1318 /* Previous should also store the scope, as instantiations along a different scope branch 1319 * should not conflict 1320 */ 1318 1321 int nmatches = 0; 1319 1322 for (Previous *p = previous; p; p = p->prev) 1320 1323 { 1321 1324 if (arrayObjectMatch(p->dedargs, dedargs, this, sc)) 1322 1325 { 1323 1326 //printf("recursive, no match %p %s\n", this, this->toChars()); 1324 1327 nmatches++; 1325 1328 } 1326 1329 /* BUG: should also check for ref param differences 1327 1330 */ 1328 1331 } 1329 1332 /* Look for 2 matches at least, because sometimes semantic3() gets run causing what appears to 1330 1333 * be recursion but isn't. 1331 1334 * Template A's constraint instantiates B, B's semantic3() run includes something that has A in its constraint. 1332 1335 * Perhaps a better solution is to always defer semantic3() rather than doing it eagerly. The risk 1333 1336 * with that is what if semantic3() fails, but our constraint "succeeded"? 1334 1337 */ 1335 1338 if (nmatches >= 2) 1336 1339 goto Lnomatch; 1337 1340
