Changeset 767
- Timestamp:
- 11/21/10 10:29:42 (14 years ago)
- Files:
-
- branches/dmd-1.x/src/backend/cg87.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgcod.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/cgelem.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod1.c (modified) (3 diffs)
- branches/dmd-1.x/src/backend/cod2.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod3.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/cod4.c (modified) (1 diff)
- branches/dmd-1.x/src/backend/elfobj.c (modified) (2 diffs)
- branches/dmd-1.x/src/backend/rtlsym.h (modified) (1 diff)
- branches/dmd-1.x/src/e2ir.c (modified) (1 diff)
- branches/dmd-1.x/src/imphint.c (modified) (1 diff)
- branches/dmd-1.x/src/mtype.c (modified) (1 diff)
- branches/dmd-1.x/src/toir.c (modified) (7 diffs)
- trunk/src/backend/cg87.c (modified) (1 diff)
- trunk/src/backend/cgcod.c (modified) (1 diff)
- trunk/src/backend/cgelem.c (modified) (2 diffs)
- trunk/src/backend/cod1.c (modified) (3 diffs)
- trunk/src/backend/cod2.c (modified) (2 diffs)
- trunk/src/backend/cod3.c (modified) (2 diffs)
- trunk/src/backend/cod4.c (modified) (1 diff)
- trunk/src/backend/elfobj.c (modified) (2 diffs)
- trunk/src/backend/rtlsym.h (modified) (1 diff)
- trunk/src/cast.c (modified) (1 diff)
- trunk/src/e2ir.c (modified) (1 diff)
- trunk/src/expression.c (modified) (1 diff)
- trunk/src/imphint.c (modified) (1 diff)
- trunk/src/mtype.c (modified) (1 diff)
- trunk/src/mtype.h (modified) (1 diff)
- trunk/src/toir.c (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/dmd-1.x/src/backend/cg87.c
r720 r767 2908 2908 // fldcw roundto0 2909 2909 // fistp long64 ptr [ESP] 2910 2910 // fldcw 8[ESP] 2911 2911 // pop lsw 2912 2912 // pop msw 2913 2913 // add ESP,4 2914 2914 2915 2915 unsigned szpush = szoff + 2; 2916 2916 if (config.flags3 & CFG3pic) 2917 2917 szpush += 2; 2918 2918 szpush = (szpush + REGSIZE - 1) & ~(REGSIZE - 1); 2919 2919 2920 2920 retregs = mST0; 2921 2921 c1 = codelem(e->E1,&retregs,FALSE); 2922 2922 2923 2923 if (szpush == REGSIZE) 2924 2924 c1 = gen1(c1,0x50 + AX); // PUSH EAX 2925 2925 else 2926 2926 c1 = genc2(c1,0x81,grex | modregrm(3,5,SP), szpush); // SUB ESP,12 2927 2927 c1 = genfwait(c1); 2928 genc1(c1,0xD9, grex |modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP]2928 genc1(c1,0xD9,modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 2929 2929 2930 2930 c1 = genfwait(c1); 2931 2931 2932 2932 if (config.flags3 & CFG3pic) 2933 2933 { 2934 genc(c1,0xC7, grex |modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto02934 genc(c1,0xC7,modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 2935 2935 code_orflag(c1, CFopsize); 2936 genc1(c1,0xD9, grex |modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP]2936 genc1(c1,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 2937 2937 } 2938 2938 else 2939 2939 c1 = genrnd(c1, CW_roundto0); // FLDCW roundto0 2940 2940 2941 2941 pop87(); 2942 2942 2943 2943 c1 = genfwait(c1); 2944 2944 gen2sib(c1,mf,grex | modregrm(0,rf,4),modregrm(0,4,SP)); // FISTP [ESP] 2945 2945 2946 2946 retregs = *pretregs & (ALLREGS | mBP); 2947 2947 if (!retregs) 2948 2948 retregs = ALLREGS; 2949 2949 c2 = allocreg(&retregs,®,tym); 2950 2950 2951 2951 c2 = genfwait(c2); // FWAIT 2952 2952 c2 = genc1(c2,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FLDCW szoff[ESP] 2953 2953 2954 2954 if (szoff > REGSIZE) 2955 2955 { szpush -= REGSIZE; 2956 2956 c2 = genpop(c2,findreglsw(retregs)); // POP lsw branches/dmd-1.x/src/backend/cgcod.c
r738 r767 1090 1090 goto L2; 1091 1091 1092 1092 case BC_try: 1093 1093 if (config.flags2 & CFG2seh) 1094 1094 { usednteh |= NTEH_try; 1095 1095 nteh_usevars(); 1096 1096 } 1097 1097 else 1098 1098 usednteh |= EHtry; 1099 1099 goto case_goto; 1100 1100 1101 1101 case BC_finally: 1102 1102 // Mark all registers as destroyed. This will prevent 1103 1103 // register assignments to variables used in finally blocks. 1104 1104 assert(!getregs(allregs)); 1105 1105 assert(!e); 1106 1106 assert(!bl->Bcode); 1107 1107 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1108 1108 if (config.flags3 & CFG3pic) 1109 1109 { 1110 int nalign = 0; 1110 1111 if (STACKALIGN == 16) 1111 { c = genc2(c,0x81,modregrm(3,5,SP),12); // SUB ESP,12 1112 { nalign = STACKALIGN - REGSIZE; 1113 c = genc2(c,0x81,modregrm(3,5,SP),nalign); // SUB ESP,nalign 1112 1114 if (I64) 1113 1115 code_orrex(c, REX_W); 1114 1116 } 1115 1117 // CALL bl->Bsucc 1116 1118 c = genc(c,0xE8,0,0,0,FLblock,(long)list_block(bl->Bsucc)); 1117 if ( STACKALIGN == 16)1118 { c = genc2(c,0x81,modregrm(3,0,SP), 12); // ADD ESP,121119 if (nalign) 1120 { c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 1119 1121 if (I64) 1120 1122 code_orrex(c, REX_W); 1121 1123 } 1122 1124 // JMP list_next(bl->Bsucc) 1123 1125 nextb = list_block(list_next(bl->Bsucc)); 1124 1126 goto L2; 1125 1127 } 1126 1128 else 1127 1129 #endif 1128 1130 { 1129 1131 // Generate a PUSH of the address of the successor to the 1130 1132 // corresponding BC_ret 1131 1133 //assert(list_block(list_next(bl->Bsucc))->BC == BC_ret); 1132 1134 // PUSH &succ 1133 1135 c = genc(c,0x68,0,0,0,FLblock,(long)list_block(list_next(bl->Bsucc))); 1134 1136 nextb = list_block(bl->Bsucc); 1135 1137 goto L2; 1136 1138 } 1137 1139 1138 1140 case BC_ret: branches/dmd-1.x/src/backend/cgelem.c
r738 r767 4137 4137 4138 4138 STATIC elem * elarray(elem *e) 4139 4139 { 4140 4140 return e; 4141 4141 } 4142 4142 4143 4143 /******************************************** 4144 4144 */ 4145 4145 4146 4146 STATIC elem * elfield(elem *e) 4147 4147 { 4148 4148 return e; 4149 4149 } 4150 4150 4151 4151 /****************************************** 4152 4152 * OPparam 4153 4153 */ 4154 4154 4155 4155 STATIC void elparamx(elem *e) 4156 4156 { 4157 elem *ex;4158 4159 4157 //printf("elparam()\n"); 4160 4158 if (e->E1->Eoper == OPrpair) 4161 4159 { 4162 4160 e->E1->Eoper = OPparam; 4163 4161 } 4164 4162 else if (e->E1->Eoper == OPpair && !el_sideeffect(e->E1)) 4165 4163 { 4166 4164 e->E1->Eoper = OPparam; 4167 e x = e->E1->E2;4165 elem *ex = e->E1->E2; 4168 4166 e->E1->E2 = e->E1->E1; 4169 4167 e->E1->E1 = ex; 4170 4168 } 4171 4169 #if 0 4172 4170 // Unfortunately, these don't work because if the last parameter 4173 4171 // is a pair, and it is a D function, the last parameter will get 4174 4172 // passed in EAX. 4175 4173 else if (e->E2->Eoper == OPrpair) 4176 4174 { 4177 4175 e->E2->Eoper = OPparam; 4178 4176 } 4179 4177 else if (e->E2->Eoper == OPpair) 4180 4178 { 4181 4179 e->E2->Eoper = OPparam; 4182 e x = e->E2->E2;4180 elem *ex = e->E2->E2; 4183 4181 e->E2->E2 = e->E2->E1; 4184 4182 e->E2->E1 = ex; 4185 4183 } 4186 4184 #endif 4187 4185 } 4188 4186 4189 4187 STATIC elem * elparam(elem *e) 4190 4188 { 4191 4189 if (!OPTIMIZER) 4192 4190 { 4193 4191 if (!I64) 4194 4192 elparamx(e); 4195 4193 } 4196 4194 return e; 4197 4195 } 4198 4196 4199 4197 /******************************** 4200 4198 * Optimize an element. This routine is recursive! 4201 4199 * Be careful not to do this if VBEs have been done (else the VBE 4202 4200 * work will be undone), or it DAGs have been built (will crash if … … 4690 4688 { 4691 4689 error(filename, linnum, "null dereference in function %s", funcsym_p->Sident); 4692 4690 e->E1->EV.Vlong = 4096; // suppress redundant messages 4693 4691 } 4694 4692 #endif 4695 4693 } 4696 4694 e = e->E1; 4697 4695 } 4698 4696 else if (OTbinary(e->Eoper)) 4699 4697 { 4700 4698 #if MARS 4701 4699 /* This is necessary as the optimizer tends to lose this information 4702 4700 */ 4703 4701 if (e->Esrcpos.Slinnum > linnum) 4704 4702 { linnum = e->Esrcpos.Slinnum; 4705 4703 filename = e->Esrcpos.Sfilename; 4706 4704 } 4707 4705 #endif 4708 4706 if (e->Eoper == OPparam) 4709 4707 { 4710 elparamx(e); 4708 if (!I64) 4709 elparamx(e); 4711 4710 } 4712 4711 postoptelem(e->E2); 4713 4712 e = e->E1; 4714 4713 } 4715 4714 else 4716 4715 break; 4717 4716 } 4718 4717 } 4719 4718 4720 4719 #endif // !SPP branches/dmd-1.x/src/backend/cod1.c
r738 r767 956 956 { t = 0; 957 957 rbase = 5; 958 958 } 959 959 else 960 960 { t = 0; 961 961 rbase = reg; 962 962 if (rbase == BP) 963 963 { static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 964 964 965 965 // IMUL r,BP,imm32 966 966 c = genc2(c,0x69,modregxrm(3,r,BP),imm32[ss1]); 967 967 goto L7; 968 968 } 969 969 } 970 970 971 971 c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 972 972 if (reg & 8) 973 973 code_orrex(c, REX_X); 974 974 if (rbase & 8) 975 975 code_orrex(c, REX_B); 976 if (I64) 977 code_orrex(c, REX_W); 976 978 977 979 if (ssflags & SSFLnobase1) 978 980 { code_last(c)->IFL1 = FLconst; 979 981 code_last(c)->IEV1.Vuns = 0; 980 982 } 981 983 L7: 982 984 if (ssflags & SSFLnobase) 983 985 { t = stackfl[f] ? 2 : 0; 984 986 rbase = 5; 985 987 } 986 988 else 987 989 { t = 2; 988 990 rbase = r; 989 991 assert(rbase != BP); 990 992 } 991 993 pcs->Irm = modregrm(t,0,4); 992 994 pcs->Isib = modregrm(ssindex_array[ssi].ss2,r & 7,rbase & 7); 993 995 if (r & 8) 994 996 code_orrex(pcs, REX_X); 995 997 if (rbase & 8) … … 1066 1068 c = cat(c,allocreg(&idxregs,®,TYoffset)); 1067 1069 1068 1070 /* If desired result is a far pointer, we'll have */ 1069 1071 /* to load another register with the segment of v */ 1070 1072 if (e1ty == TYfptr) 1071 1073 { 1072 1074 unsigned msreg; 1073 1075 1074 1076 idxregs |= mMSW & ALLREGS & ~keepmsk; 1075 1077 c = cat(c,allocreg(&idxregs,&msreg,TYfptr)); 1076 1078 msreg = findregmsw(idxregs); 1077 1079 /* MOV msreg,segreg */ 1078 1080 c = genregs(c,0x8C,segfl[f],msreg); 1079 1081 } 1080 1082 opsave = pcs->Iop; 1081 1083 flagsave = pcs->Iflags; 1082 1084 pcs->Iop = 0x8D; 1083 1085 code_newreg(pcs, reg); 1084 1086 if (!I16) 1085 1087 pcs->Iflags &= ~CFopsize; 1088 if (I64) 1089 pcs->Irex |= REX_W; 1086 1090 c = gen(c,pcs); /* LEA idxreg,EA */ 1087 1091 cssave(e1,idxregs,TRUE); 1088 1092 if (!I16) 1089 1093 pcs->Iflags = flagsave; 1090 1094 if (stackfl[f] && (config.wflags & WFssneds)) // if pointer into stack 1091 1095 pcs->Iflags |= CFss; // add SS: override 1092 1096 pcs->Iop = opsave; 1093 1097 pcs->IFL1 = FLoffset; 1094 1098 pcs->IEV1.Vuns = 0; 1095 1099 setaddrmode(pcs, idxregs); 1096 1100 } 1097 1101 freenode(e12); 1098 1102 if (e1free) 1099 1103 freenode(e1); 1100 1104 goto Lptr; 1101 1105 } 1102 1106 1103 1107 L1: 1104 1108 1105 1109 /* The rest of the cases could be a far pointer */ … … 2846 2850 { unsigned lsreg; 2847 2851 LF1: 2848 2852 reg = findregmsw(retregs); 2849 2853 lsreg = findreglsw(retregs); 2850 2854 floatreg = TRUE; /* use float register */ 2851 2855 reflocal = TRUE; 2852 2856 ce = genc1(ce,0x89, /* MOV floatreg+2,reg */ 2853 2857 modregrm(2,reg,BPRM),FLfltreg,REGSIZE); 2854 2858 genc1(ce,0x89, /* MOV floatreg,lsreg */ 2855 2859 modregrm(2,lsreg,BPRM),FLfltreg,0); 2856 2860 if (tym1 == TYifunc) 2857 2861 gen1(ce,0x9C); // PUSHF 2858 2862 genc1(ce,0xFF, /* CALL [floatreg] */ 2859 2863 modregrm(2,3,BPRM),FLfltreg,0); 2860 2864 } 2861 2865 else 2862 2866 { 2863 2867 LF2: 2864 2868 reg = findreg(retregs); 2865 2869 ce = gen2(ce,0xFF,modregrmx(3,2,reg)); /* CALL reg */ 2870 if (I64) 2871 code_orrex(ce, REX_W); 2866 2872 } 2867 2873 } 2868 2874 else 2869 2875 { 2870 2876 if (tym1 == TYifunc) 2871 2877 c = gen1(c,0x9C); // PUSHF 2872 2878 // CALL [function] 2873 2879 cs.Iflags = 0; 2874 2880 cgstate.stackclean++; 2875 2881 ce = loadea(e11,&cs,0xFF,farfunc ? 3 : 2,0,keepmsk,(ALLREGS|mES|mBP) & ~fregsaved); 2876 2882 cgstate.stackclean--; 2877 2883 freenode(e11); 2878 2884 } 2879 2885 s = NULL; 2880 2886 } 2881 2887 c = cat(c,ce); 2882 2888 freenode(e1); 2883 2889 2884 2890 /* See if we will need the frame pointer. 2885 2891 Calculate it here so we can possibly use BP to fix the stack. branches/dmd-1.x/src/backend/cod2.c
r738 r767 636 636 } 637 637 } 638 638 rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 639 639 cs.IEV2.Vint = i; 640 640 L3: 641 641 op1 ^= byte; 642 642 cs.Iflags |= word; 643 643 if (rval) 644 644 { cs.Iop = op1 ^ 2; 645 645 mode = rreg; 646 646 } 647 647 else 648 648 cs.Iop = 0x81; 649 649 cs.Irm = modregrm(3,mode&7,reg&7); 650 650 if (mode & 8) 651 651 cs.Irex |= REX_R; 652 652 if (reg & 8) 653 653 cs.Irex |= REX_B; 654 654 if (I64 && sz == 8) 655 655 cs.Irex |= REX_W; 656 if (I64 && byte && reg >= 4) 657 cs.Irex |= REX; 656 658 cs.IFL2 = (e2->Eoper == OPconst) ? FLconst : el_fl(e2); 657 659 /* Modify instruction for special cases */ 658 660 switch (e->Eoper) 659 661 { case OPadd: 660 662 { int iop; 661 663 662 664 if (i == 1) 663 665 iop = 0; /* INC reg */ 664 666 else if (i == -1) 665 667 iop = 8; /* DEC reg */ 666 668 else 667 669 break; 668 670 cs.Iop = (0x40 | iop | reg) ^ byte; 669 671 if ((byte && *pretregs & mPSW) || I64) 670 672 { cs.Irm = modregrm(3,0,reg & 7) | iop; 671 673 cs.Iop = 0xFF; 672 674 } 673 675 break; 674 676 } 675 677 case OPand: … … 3294 3296 c2->Iflags = CFopsize; 3295 3297 offset += 2; 3296 3298 c3 = cat(c3,c2); 3297 3299 } 3298 3300 if (numbytes & 1) 3299 3301 { // MOV byte ptr offset[reg],vreg 3300 3302 c2 = gen2(CNIL,0x88,modregxrmx(2,vreg,reg)); 3301 3303 c2->IEVoffset1 = offset; 3302 3304 c2->IFL1 = FLconst; 3303 3305 c3 = cat(c3,c2); 3304 3306 } 3305 3307 fixres: 3306 3308 return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 3307 3309 } 3308 3310 } 3309 3311 3310 3312 // Get nbytes into CX 3311 3313 retregs2 = mCX; 3312 3314 if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 3313 3315 { 3314 remainder = numbytes & ( REGSIZE- 1);3315 numwords = numbytes / REGSIZE;// number of words3316 remainder = numbytes & (4 - 1); 3317 numwords = numbytes / 4; // number of words 3316 3318 op = 0xAB; // moving by words 3317 3319 c1 = getregs(mCX); 3318 3320 c1 = movregconst(c1,CX,numwords,I64?64:0); // # of bytes/words 3319 3321 } 3320 3322 else 3321 3323 { 3322 3324 remainder = 0; 3323 3325 op = 0xAA; // must move by bytes 3324 3326 c1 = codelem(e2->E1,&retregs2,FALSE); 3325 3327 } 3326 3328 3327 3329 // Get val into AX 3328 3330 3329 3331 retregs3 = mAX; 3330 3332 if (!I16 && e2->E2->Eoper == OPconst) 3331 3333 { 3332 3334 c1 = regwithvalue(c1, mAX, value, NULL, I64?64:0); 3333 3335 freenode(e2->E2); 3334 3336 } 3335 3337 else branches/dmd-1.x/src/backend/cod3.c
r760 r767 2287 2287 2288 2288 /* Skip over return address */ 2289 2289 thunkty = tybasic(sthunk->ty()); 2290 2290 if (tyfarfunc(thunkty)) 2291 2291 p += I32 ? 8 : tysize[TYfptr]; /* far function */ 2292 2292 else 2293 2293 p += tysize[TYnptr]; 2294 2294 2295 2295 if (!I16) 2296 2296 { 2297 2297 /* 2298 2298 Generate: 2299 2299 ADD p[ESP],d 2300 2300 For direct call: 2301 2301 JMP sfunc 2302 2302 For virtual call: 2303 2303 MOV EAX, p[ESP] EAX = this 2304 2304 MOV EAX, d2[EAX] EAX = this->vptr 2305 2305 JMP i[EAX] jump to virtual function 2306 2306 */ 2307 unsigned reg = 0; 2308 if ((targ_ptrdiff_t)d < 0) 2309 { 2310 d = -d; 2311 reg = 5; // switch from ADD to SUB 2312 } 2307 2313 if (thunkty == TYmfunc) 2308 2314 { // ADD ECX,d 2309 2315 c = CNIL; 2310 2316 if (d) 2311 c = genc2(c,0x81,modregrm(3, 0,CX),d);2317 c = genc2(c,0x81,modregrm(3,reg,CX),d); 2312 2318 } 2313 2319 else if (thunkty == TYjfunc) 2314 2320 { // ADD EAX,d 2315 2321 c = CNIL; 2316 2322 if (d) 2317 c = genc2(c,0x81,modregrm(3, 0,AX),d);2323 c = genc2(c,0x81,modregrm(3,reg,I64 ? DI : AX),d); 2318 2324 } 2319 2325 else 2320 2326 { 2321 c = genc(CNIL,0x81,modregrm(2, 0,4),2327 c = genc(CNIL,0x81,modregrm(2,reg,4), 2322 2328 FLconst,p, // to this 2323 2329 FLconst,d); // ADD p[ESP],d 2324 2330 c->Isib = modregrm(0,4,SP); 2325 2331 } 2326 2332 if (I64) 2327 2333 c->Irex |= REX_W; 2328 2334 } 2329 2335 else 2330 2336 { 2331 2337 /* 2332 2338 Generate: 2333 2339 MOV BX,SP 2334 2340 ADD [SS:] p[BX],d 2335 2341 For direct call: 2336 2342 JMP sfunc 2337 2343 For virtual call: 2338 2344 MOV BX, p[BX] BX = this 2339 2345 MOV BX, d2[BX] BX = this->vptr 2340 2346 JMP i[BX] jump to virtual function 2341 2347 */ … … 4552 4558 case FLfunc: /* function call */ 4553 4559 s = uev->sp.Vsym; /* symbol pointer */ 4554 4560 #if !TARGET_FLAT 4555 4561 if (tyfarfunc(s->ty())) 4556 4562 { /* Large code references are always absolute */ 4557 4563 FLUSH(); 4558 4564 offset += reftoident(cseg,offset,s,0,flags) - 4; 4559 4565 } 4560 4566 else if (s->Sseg == cseg && 4561 4567 (s->Sclass == SCstatic || s->Sclass == SCglobal) && 4562 4568 s->Sxtrnnum == 0 && flags & CFselfrel) 4563 4569 { /* if we know it's relative address */ 4564 4570 ad = s->Soffset - OFFSET() - 4; 4565 4571 goto L1; 4566 4572 } 4567 4573 else 4568 4574 #endif 4569 4575 { 4570 4576 assert(!(TARGET_FLAT && tyfarfunc(s->ty()))); 4571 4577 FLUSH(); 4572 reftoident(cseg,offset,s, 0,flags);4578 reftoident(cseg,offset,s,val,flags); 4573 4579 } 4574 4580 break; 4575 4581 4576 4582 case FLblock: /* displacement to another block */ 4577 4583 ad = uev->Vblock->Boffset - OFFSET() - 4; 4578 4584 //printf("FLblock: funcoffset = %x, OFFSET = %x, Boffset = %x, ad = %x\n", funcoffset, OFFSET(), uev->Vblock->Boffset, ad); 4579 4585 goto L1; 4580 4586 4581 4587 case FLblockoff: 4582 4588 FLUSH(); 4583 4589 assert(uev->Vblock); 4584 4590 //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 4585 4591 reftocodseg(cseg,offset,uev->Vblock->Boffset); 4586 4592 break; 4587 4593 4588 4594 default: 4589 4595 #ifdef DEBUG 4590 4596 WRFL(fl); 4591 4597 #endif 4592 4598 assert(0); branches/dmd-1.x/src/backend/cod4.c
r738 r767 1006 1006 cs.Iop = op1 ^ 2; // toggle direction bit 1007 1007 if (forccs) 1008 1008 cs.Iflags |= CFpsw; 1009 1009 reverse = 2; // remember we toggled it 1010 1010 cl = gen(cl,&cs); 1011 1011 c = cat(cr,cl); 1012 1012 retregs = 0; /* to trigger a bug if we attempt to use it */ 1013 1013 } 1014 1014 else // evaluate e2 into register 1015 1015 { 1016 1016 retregs = (byte) ? BYTEREGS : ALLREGS; // pick working reg 1017 1017 if (tyml == TYhptr) 1018 1018 retregs &= ~mCX; // need CX for shift count 1019 1019 cr = scodelem(e->E2,&retregs,0,TRUE); // get rvalue 1020 1020 cl = getlvalue(&cs,e1,retregs); // get lvalue 1021 1021 cl = cat(cl,modEA(&cs)); 1022 1022 cs.Iop = op1; 1023 1023 if (sz <= REGSIZE || tyfv(tyml)) 1024 1024 { reg = findreg(retregs); 1025 1025 code_newreg(&cs, reg); // OP1 EA,reg 1026 if (sz == 1 && reg >= 4 && I64) 1027 cs.Irex |= REX; 1026 1028 } 1027 1029 else if (tyml == TYhptr) 1028 1030 { unsigned mreg,lreg; 1029 1031 1030 1032 mreg = findregmsw(retregs); 1031 1033 lreg = findreglsw(retregs); 1032 1034 cl = cat(cl,getregs(retregs | mCX)); 1033 1035 1034 1036 // If h -= l, convert to h += -l 1035 1037 if (e->Eoper == OPminass) 1036 1038 { 1037 1039 cl = gen2(cl,0xF7,modregrm(3,3,mreg)); // NEG mreg 1038 1040 gen2(cl,0xF7,modregrm(3,3,lreg)); // NEG lreg 1039 1041 code_orflag(cl,CFpsw); 1040 1042 genc2(cl,0x81,modregrm(3,3,mreg),0); // SBB mreg,0 1041 1043 } 1042 1044 cs.Iop = 0x01; 1043 1045 cs.Irm |= modregrm(0,lreg,0); 1044 1046 cl = gen(cl,&cs); // ADD EA,lreg 1045 1047 code_orflag(cl,CFpsw); branches/dmd-1.x/src/backend/elfobj.c
r714 r767 2752 2752 if (s->Sclass == SCstatic) 2753 2753 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2754 2754 else 2755 2755 relinfo = RI_TYPE_TLS_IE; 2756 2756 } 2757 2757 else 2758 2758 { 2759 2759 if (s->Sclass == SCstatic) 2760 2760 relinfo = RI_TYPE_TLS_LE; 2761 2761 else 2762 2762 relinfo = RI_TYPE_TLS_IE; 2763 2763 } 2764 2764 } 2765 2765 } 2766 2766 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2767 2767 { 2768 2768 relinfo = R_X86_64_64; 2769 2769 } 2770 2770 //printf("\t\t************* adding relocation\n"); 2771 2771 targ_size_t v = 0; 2772 if (I64 && re linfo == R_X86_64_PC32)2772 if (I64 && retsize == 4) 2773 2773 { 2774 2774 assert(retsize == 4); 2775 2775 if (val > 0xFFFFFFFF) 2776 2776 { /* The value to be added is bigger than 32 bits, so we 2777 2777 * transfer it to the 64 bit addend of the fixup record 2778 2778 */ 2779 2779 v = val; 2780 2780 val = 0; 2781 2781 } 2782 2782 } 2783 2783 #if 0 2784 2784 targ_size_t v = (relinfo == R_X86_64_PC32) ? -4 : 0; 2785 2785 if (relinfo == R_X86_64_PC32 && flags & CFaddend8) 2786 2786 v = -8; 2787 2787 #endif 2788 2788 elf_addrel(seg,offset,relinfo,refseg,v); 2789 2789 } 2790 2790 outaddrval: 2791 2791 if (retsize == 8) 2792 2792 buf->write64(val); … … 2990 2990 if (I64) 2991 2991 buf->writeByte(REX | REX_W); 2992 2992 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2993 2993 if (I64) 2994 2994 buf->writeByte(REX | REX_W); 2995 2995 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2996 2996 if (I64) 2997 2997 buf->writeByte(REX | REX_W); 2998 2998 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2999 2999 3000 3000 if (I32) buf->writeByte(0x61); // POPAD 3001 3001 buf->writeByte(0xC3); /* ret */ 3002 3002 SegData[seg]->SDoffset = buf->size(); 3003 3003 } 3004 3004 3005 3005 /* Add reference to constructor into ".ctors" segment 3006 3006 */ 3007 3007 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 3008 3008 3009 3009 Outbuffer *buf = SegData[seg]->SDbuf; 3010 buf->write32(codeOffset); 3010 if (I64) 3011 buf->write64(codeOffset); 3012 else 3013 buf->write32(codeOffset); 3011 3014 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 3012 3015 SegData[seg]->SDoffset += NPTRSIZE; 3013 3016 } 3014 3017 3015 3018 #endif 3016 3019 3017 3020 /************************************* 3018 3021 */ 3019 3022 3020 3023 void elfobj_gotref(symbol *s) 3021 3024 { 3022 3025 //printf("elfobj_gotref(%x '%s', %d)\n",s,s->Sident, s->Sclass); 3023 3026 switch(s->Sclass) 3024 3027 { 3025 3028 case SCstatic: 3026 3029 case SClocstat: 3027 3030 s->Sfl = FLgotoff; 3028 3031 break; 3029 3032 3030 3033 case SCextern: branches/dmd-1.x/src/backend/rtlsym.h
r738 r767 47 47 SYMBOL_MARS(MONITOR_PROLOG, FLfunc,FREGSAVED,"_d_monitor_prolog",0,t) \ 48 48 SYMBOL_MARS(MONITOR_EPILOG, FLfunc,FREGSAVED,"_d_monitor_epilog",0,t) \ 49 49 SYMBOL_MARS(DCOVER, FLfunc,FREGSAVED,"_d_cover_register", 0, t) \ 50 50 SYMBOL_MARS(DASSERT, FLfunc,FREGSAVED,"_d_assert", SFLexit, t) \ 51 51 SYMBOL_MARS(DASSERTM, FLfunc,FREGSAVED,"_d_assertm", SFLexit, t) \ 52 52 SYMBOL_MARS(DASSERT_MSG, FLfunc,FREGSAVED,"_d_assert_msg", SFLexit, t) \ 53 53 SYMBOL_MARS(DUNITTEST, FLfunc,FREGSAVED,"_d_unittest", 0, t) \ 54 54 SYMBOL_MARS(DUNITTESTM, FLfunc,FREGSAVED,"_d_unittestm", 0, t) \ 55 55 SYMBOL_MARS(DUNITTEST_MSG, FLfunc,FREGSAVED,"_d_unittest_msg", 0, t) \ 56 56 SYMBOL_MARS(DARRAY, FLfunc,FREGSAVED,"_d_array_bounds", SFLexit, t) \ 57 57 SYMBOL_MARS(DINVARIANT, FLfunc,FREGSAVED,"D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \ 58 58 SYMBOL_MARS(_DINVARIANT, FLfunc,FREGSAVED,"_D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \ 59 59 SYMBOL_MARS(MEMCPY, FLfunc,FREGSAVED,"memcpy", 0, t) \ 60 60 SYMBOL_MARS(MEMSET8, FLfunc,FREGSAVED,"memset", 0, t) \ 61 61 SYMBOL_MARS(MEMSET16, FLfunc,FREGSAVED,"_memset16", 0, t) \ 62 62 SYMBOL_MARS(MEMSET32, FLfunc,FREGSAVED,"_memset32", 0, t) \ 63 63 SYMBOL_MARS(MEMSET64, FLfunc,FREGSAVED,"_memset64", 0, t) \ 64 64 SYMBOL_MARS(MEMSET128, FLfunc,FREGSAVED,"_memset128",0, t) \ 65 65 SYMBOL_MARS(MEMSET80, FLfunc,FREGSAVED,"_memset80", 0, t) \ 66 66 SYMBOL_MARS(MEMSET160, FLfunc,FREGSAVED,"_memset160",0, t) \ 67 SYMBOL_MARS(MEMSETFLOAT, FLfunc,FREGSAVED,"_memsetFloat", 0, t) \ 68 SYMBOL_MARS(MEMSETDOUBLE, FLfunc,FREGSAVED,"_memsetDouble", 0, t) \ 67 69 SYMBOL_MARS(MEMSETN, FLfunc,FREGSAVED,"_memsetn", 0, t) \ 68 70 SYMBOL_MARS(MODULO, FLfunc,FREGSAVED,"_modulo", 0, t) \ 69 71 SYMBOL_MARS(MONITORENTER, FLfunc,FREGSAVED,"_d_monitorenter",0, t) \ 70 72 SYMBOL_MARS(MONITOREXIT, FLfunc,FREGSAVED,"_d_monitorexit",0, t) \ 71 73 SYMBOL_MARS(CRITICALENTER, FLfunc,FREGSAVED,"_d_criticalenter",0, t) \ 72 74 SYMBOL_MARS(CRITICALEXIT, FLfunc,FREGSAVED,"_d_criticalexit",0, t) \ 73 75 SYMBOL_MARS(SWITCH_STRING, FLfunc,FREGSAVED,"_d_switch_string", 0, t) \ 74 76 SYMBOL_MARS(SWITCH_USTRING,FLfunc,FREGSAVED,"_d_switch_ustring", 0, t) \ 75 77 SYMBOL_MARS(SWITCH_DSTRING,FLfunc,FREGSAVED,"_d_switch_dstring", 0, t) \ 76 78 SYMBOL_MARS(DSWITCHERR, FLfunc,FREGSAVED,"_d_switch_error", SFLexit, t) \ 77 79 SYMBOL_MARS(DHIDDENFUNC, FLfunc,FREGSAVED,"_d_hidden_func", 0, t) \ 78 80 SYMBOL_MARS(NEWCLASS, FLfunc,FREGSAVED,"_d_newclass", 0, t) \ 79 81 SYMBOL_MARS(NEWARRAYT, FLfunc,FREGSAVED,"_d_newarrayT", 0, t) \ 80 82 SYMBOL_MARS(NEWARRAYIT, FLfunc,FREGSAVED,"_d_newarrayiT", 0, t) \ 81 83 SYMBOL_MARS(NEWARRAYMT, FLfunc,FREGSAVED,"_d_newarraymT", 0, tv) \ 82 84 SYMBOL_MARS(NEWARRAYMIT, FLfunc,FREGSAVED,"_d_newarraymiT", 0, tv) \ 83 85 SYMBOL_MARS(ARRAYLITERALT, FLfunc,FREGSAVED,"_d_arrayliteralT", 0, tv) \ 84 86 SYMBOL_MARS(ASSOCARRAYLITERALT, FLfunc,FREGSAVED,"_d_assocarrayliteralT", 0, tv) \ 85 87 SYMBOL_MARS(ASSOCARRAYLITERALTX, FLfunc,FREGSAVED,"_d_assocarrayliteralTX", 0, t) \ 86 88 SYMBOL_MARS(CALLFINALIZER, FLfunc,FREGSAVED,"_d_callfinalizer", 0, t) \ branches/dmd-1.x/src/e2ir.c
r738 r767 495 495 /***************************************** 496 496 * Evaluate elem and convert to dynamic array. 497 497 */ 498 498 499 499 elem *eval_Darray(IRState *irs, Expression *e) 500 500 { 501 501 elem *ex; 502 502 503 503 ex = e->toElem(irs); 504 504 return array_toDarray(e->type, ex); 505 505 } 506 506 507 507 /************************************ 508 508 */ 509 509 510 510 elem *sarray_toDarray(Loc loc, Type *tfrom, Type *tto, elem *e) 511 511 { 512 512 //printf("sarray_toDarray()\n"); 513 513 //elem_print(e); 514 514 515 elem *elen;516 515 unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger(); 517 516 518 517 if (tto) 519 518 { 520 519 unsigned fsize = tfrom->nextOf()->size(); 521 520 unsigned tsize = tto->nextOf()->size(); 522 521 523 522 if ((dim * fsize) % tsize != 0) 524 523 { 525 524 Lerr: 526 525 error(loc, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars()); 527 526 } 528 527 dim = (dim * fsize) / tsize; 529 528 } 530 529 L1: 531 ele n = el_long(TYsize_t, dim);530 elem *elen = el_long(TYsize_t, dim); 532 531 e = el_una(OPaddr, TYnptr, e); 533 532 e = el_pair(TYdarray, elen, e); 534 533 return e; 535 534 } 536 535 537 536 /******************************************* 538 537 * Set an array pointed to by eptr to evalue: 539 538 * eptr[0..edim] = evalue; 540 539 * Input: 541 540 * eptr where to write the data to 542 541 * evalue value to write 543 542 * edim number of times to write evalue to eptr[] 544 543 * tb type of evalue 545 544 */ 546 545 547 546 elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue) 548 547 { int r; 549 548 elem *e; 550 549 int sz = tb->size(); 551 550 552 if (tb->ty == Tfloat80 || tb->ty == Timaginary80) 553 r = RTLSYM_MEMSET80; 554 else if (tb->ty == Tcomplex80) 555 r = RTLSYM_MEMSET160; 556 else if (tb->ty == Tcomplex64) 557 r = RTLSYM_MEMSET128; 558 else 559 { 560 switch (sz) 561 { 562 case 1: r = RTLSYM_MEMSET8; break; 563 case 2: r = RTLSYM_MEMSET16; break; 564 case 4: r = RTLSYM_MEMSET32; break; 565 case 8: r = RTLSYM_MEMSET64; break; 566 case 16: r = RTLSYM_MEMSET128; break; 567 568 default: 569 r = RTLSYM_MEMSETN; 570 evalue = el_una(OPaddr, TYnptr, evalue); 571 elem *esz = el_long(TYsize_t, sz); 572 e = el_params(esz, edim, evalue, eptr, NULL); 573 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); 574 return e; 575 } 551 switch (tb->ty) 552 { 553 case Tfloat80: 554 case Timaginary80: 555 r = RTLSYM_MEMSET80; 556 break; 557 case Tcomplex80: 558 r = RTLSYM_MEMSET160; 559 break; 560 case Tcomplex64: 561 r = RTLSYM_MEMSET128; 562 break; 563 case Tfloat32: 564 case Timaginary32: 565 if (I32) 566 goto Ldefault; // legacy binary compatibility 567 r = RTLSYM_MEMSETFLOAT; 568 break; 569 case Tfloat64: 570 case Timaginary64: 571 if (I32) 572 goto Ldefault; // legacy binary compatibility 573 r = RTLSYM_MEMSETDOUBLE; 574 break; 575 576 default: 577 Ldefault: 578 switch (sz) 579 { 580 case 1: r = RTLSYM_MEMSET8; break; 581 case 2: r = RTLSYM_MEMSET16; break; 582 case 4: r = RTLSYM_MEMSET32; break; 583 case 8: r = RTLSYM_MEMSET64; break; 584 case 16: r = RTLSYM_MEMSET128; break; 585 586 default: 587 r = RTLSYM_MEMSETN; 588 evalue = el_una(OPaddr, TYnptr, evalue); 589 elem *esz = el_long(TYsize_t, sz); 590 e = el_params(esz, edim, evalue, eptr, NULL); 591 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); 592 return e; 593 } 594 break; 576 595 } 577 596 if (sz > 1 && sz <= 8 && 578 597 evalue->Eoper == OPconst && el_allbits(evalue, 0)) 579 598 { 580 599 r = RTLSYM_MEMSET8; 581 600 edim = el_bin(OPmul, TYsize_t, edim, el_long(TYsize_t, sz)); 582 601 } 583 602 584 603 if (tybasic(evalue->Ety) == TYstruct) 585 604 { 586 605 evalue = el_una(OPstrpar, TYstruct, evalue); 587 606 evalue->ET = evalue->E1->ET; 588 607 } 589 608 590 609 // Be careful about parameter side effect ordering 591 610 if (r == RTLSYM_MEMSET8) 592 611 { 593 612 e = el_param(edim, evalue); 594 613 e = el_bin(OPmemset,TYnptr,eptr,e); 595 614 } branches/dmd-1.x/src/imphint.c
r606 r767 1 1 2 2 3 3 // Compiler implementation of the D programming language 4 4 // Copyright (c) 2010 by Digital Mars 5 5 // All Rights Reserved 6 6 // written by Walter Bright 7 7 // http://www.digitalmars.com 8 8 // License for redistribution is by either the Artistic License 9 9 // in artistic.txt, or the GNU General Public License in gnu.txt. 10 10 // See the included readme.txt for details. 11 11 12 12 #include <stdio.h> 13 13 #include <stdlib.h> 14 14 #include <ctype.h> 15 15 #include <assert.h> 16 16 #include <string.h> 17 17 18 #include "mars.h" 19 18 20 /****************************************** 19 21 * Looks for undefined identifier s to see 20 22 * if it might be undefined because an import 21 23 * was not specified. 22 24 * Not meant to be a comprehensive list of names in each module, 23 25 * just the most common ones. 24 26 */ 25 27 26 28 const char *importHint(const char *s) 27 29 { 28 30 #if DMDV1 29 31 static const char *modules[] = 30 32 { "std.c.stdio", 31 33 "std.stdio", 32 34 "std.math", 35 "std.c.stdarg", 33 36 }; 34 37 static const char *names[] = 35 38 { 36 39 "printf", NULL, 37 40 "writefln", NULL, 38 41 "sin", "cos", "sqrt", "fabs", NULL, 42 "__va_argsave_t", NULL, 39 43 }; 40 44 #else 41 45 static const char *modules[] = 42 46 { "core.stdc.stdio", 43 47 "std.stdio", 44 48 "std.math", 49 "std.c.stdarg", 45 50 }; 46 51 static const char *names[] = 47 52 { 48 53 "printf", NULL, 49 54 "writeln", NULL, 50 55 "sin", "cos", "sqrt", "fabs", NULL, 56 "__va_argsave_t", NULL, 51 57 }; 52 58 #endif 53 59 int m = 0; 54 60 for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) 55 61 { 56 62 const char *p = names[n]; 57 63 if (p == NULL) 58 64 { m++; 59 65 continue; 60 66 } 61 67 assert(m < sizeof(modules)/sizeof(modules[0])); 62 68 if (strcmp(s, p) == 0) 63 69 return modules[m]; 64 70 } 65 71 return NULL; // didn't find it 66 72 } 67 73 68 74 #if UNITTEST 69 75 70 76 void unittest_importHint() branches/dmd-1.x/src/mtype.c
r742 r767 3453 3454 return; 3454 3455 } 3455 3456 if (scx->scopesym == scopesym) 3456 3457 { 3457 3458 t = t->semantic(loc, scx); 3458 3459 break; 3459 3460 } 3460 3461 } 3461 3462 } 3462 3463 } 3463 3464 } 3464 3465 if (t->ty == Ttuple) 3465 3466 *pt = t; 3466 3467 else if (t->ty == Ttypeof) 3467 3468 *pt = t->semantic(loc, sc); 3468 3469 else 3469 3470 *pt = t->merge(); 3470 3471 } 3471 3472 if (!s) 3472 3473 { 3473 error(loc, "identifier '%s' is not defined", toChars()); 3474 const char *p = toChars(); 3475 const char *n = importHint(p); 3476 if (n) 3477 error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n); 3478 else 3479 { 3480 Identifier *id = new Identifier(p, TOKidentifier); 3481 s = sc->search_correct(id); 3482 if (s) 3483 error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars()); 3484 else 3485 error(loc, "undefined identifier %s", p); 3486 } 3474 3487 } 3475 3488 } 3476 3489 3477 3490 /***************************** TypeIdentifier *****************************/ 3478 3491 3479 3492 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) 3480 3493 : TypeQualified(Tident, loc) 3481 3494 { 3482 3495 this->ident = ident; 3483 3496 } 3484 3497 3485 3498 3486 3499 Type *TypeIdentifier::syntaxCopy() 3487 3500 { 3488 3501 TypeIdentifier *t; 3489 3502 3490 3503 t = new TypeIdentifier(loc, ident); 3491 3504 t->syntaxCopyHelper(this); 3492 3505 return t; 3493 3506 } branches/dmd-1.x/src/toir.c
r728 r767 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-20 09by Digital Mars3 // Copyright (c) 1999-2010 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 /* Code to help convert to the intermediate representation 12 12 * of the compiler back end. 13 13 */ 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include <complex.h> 19 19 20 20 #include "lexer.h" 21 21 #include "expression.h" 22 22 #include "mtype.h" 23 23 #include "dsymbol.h" … … 129 129 ethis = el_una(OPaddr, TYnptr, ethis); 130 130 } 131 131 } 132 132 else 133 133 { /* No 'this' pointer for current function, 134 134 * use NULL if no references to the current function's frame 135 135 */ 136 136 ethis = el_long(TYnptr, 0); 137 137 #if DMDV2 138 138 if (thisfd->closureVars.dim) 139 139 #else 140 140 if (thisfd->nestedFrameRef) 141 141 #endif 142 142 { /* OPframeptr is an operator that gets the frame pointer 143 143 * for the current function, i.e. for the x86 it gets 144 144 * the value of EBP 145 145 */ 146 146 ethis->Eoper = OPframeptr; 147 147 } 148 148 } 149 //if (fdparent != thisfd) ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, 0x18)); 149 150 } 150 151 else 151 152 { 152 153 if (!irs->sthis) // if no frame pointer for this function 153 154 { 154 155 fd->error(loc, "is a nested function and cannot be accessed from %s", irs->getFunc()->toChars()); 155 156 ethis = el_long(TYnptr, 0); // error recovery 156 157 } 157 158 else 158 159 { 159 160 ethis = el_var(irs->sthis); 160 161 Dsymbol *s = thisfd; 161 162 while (fd != s) 162 163 { /* Go up a nesting level, i.e. we need to find the 'this' 163 164 * of an enclosing function. 164 165 * Our 'enclosing function' may also be an inner class. 165 166 */ 166 167 167 168 //printf("\ts = '%s'\n", s->toChars()); 168 169 thisfd = s->isFuncDeclaration(); … … 172 173 if (fdparent == s->toParent2()) 173 174 break; 174 175 if (thisfd->isNested()) 175 176 { 176 177 FuncDeclaration *p = s->toParent2()->isFuncDeclaration(); 177 178 #if DMDV2 178 179 if (!p || p->closureVars.dim) 179 180 #else 180 181 if (!p || p->nestedFrameRef) 181 182 #endif 182 183 ethis = el_una(OPind, TYnptr, ethis); 183 184 } 184 185 else if (thisfd->vthis) 185 186 { 186 187 } 187 188 else 188 189 // Error should have been caught by front end 189 190 assert(0); 190 191 } 191 192 else 192 { /* Enclosed by a class. That means the current193 * function must be a member function of that class.193 { /* Enclosed by an aggregate. That means the current 194 * function must be a member function of that aggregate. 194 195 */ 195 196 ClassDeclaration *cd = s->isClassDeclaration(); 196 197 if (!cd) 197 198 goto Lnoframe; 198 199 if (//cd->baseClass == fd || 199 200 fd->isClassDeclaration() && 200 201 fd->isClassDeclaration()->isBaseOf(cd, NULL)) 201 202 break; 202 203 if (!cd->isNested() || !cd->vthis) 203 204 { 204 205 Lnoframe: 205 206 irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars()); 206 207 return el_long(TYnptr, 0); // error recovery 207 208 } 208 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TY int, cd->vthis->offset));209 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, cd->vthis->offset)); 209 210 ethis = el_una(OPind, TYnptr, ethis); 210 211 if (fdparent == s->toParent2()) 211 212 break; 212 213 if (fd == s->toParent2()) 213 214 { 214 215 /* Remember that frames for functions that have no 215 216 * nested references are skipped in the linked list 216 217 * of frames. 217 218 */ 218 219 #if DMDV2 219 220 if (s->toParent2()->isFuncDeclaration()->closureVars.dim) 220 221 #else 221 222 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) 222 223 #endif 223 224 ethis = el_una(OPind, TYnptr, ethis); 224 225 break; 225 226 } 226 227 if (s->toParent2()->isFuncDeclaration()) 227 228 { 228 229 /* Remember that frames for functions that have no … … 300 301 } 301 302 } 302 303 else if (thisfd->vthis && 303 304 (cdp == thisfd->toParent2() || 304 305 (cdp->isClassDeclaration() && 305 306 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset) 306 307 ) 307 308 ) 308 309 ) 309 310 { /* Class we're new'ing is at the same level as thisfd 310 311 */ 311 312 assert(offset == 0); // BUG: should handle this case 312 313 ethis = el_var(irs->sthis); 313 314 } 314 315 else 315 316 { 316 317 ethis = getEthis(loc, irs, ad->toParent2()); 317 318 ethis = el_una(OPaddr, TYnptr, ethis); 318 319 } 319 320 320 ey = el_bin(OPadd, TYnptr, ey, el_long(TY int, ad->vthis->offset));321 ey = el_bin(OPadd, TYnptr, ey, el_long(TYsize_t, ad->vthis->offset)); 321 322 ey = el_una(OPind, TYnptr, ey); 322 323 ey = el_bin(OPeq, TYnptr, ey, ethis); 323 324 return ey; 324 325 } 325 326 #endif 326 327 327 328 /******************************************* 328 329 * Convert intrinsic function to operator. 329 330 * Returns that operator, -1 if not an intrinsic function. 330 331 */ 331 332 332 333 int intrinsic_op(char *name) 333 334 { 334 335 //printf("intrinsic_op(%s)\n", name); 335 336 static const char *namearray[] = 336 337 { 337 338 #if DMDV1 338 339 "4math3cosFeZe", 339 340 "4math3sinFeZe", 340 341 "4math4fabsFeZe", … … 347 348 "4math6rndtolFeZl", 348 349 "4math6yl2xp1FeeZe", 349 350 350 351 "9intrinsic2btFPkkZi", 351 352 "9intrinsic3bsfFkZi", 352 353 "9intrinsic3bsrFkZi", 353 354 "9intrinsic3btcFPkkZi", 354 355 "9intrinsic3btrFPkkZi", 355 356 "9intrinsic3btsFPkkZi", 356 357 "9intrinsic3inpFkZh", 357 358 "9intrinsic4inplFkZk", 358 359 "9intrinsic4inpwFkZt", 359 360 "9intrinsic4outpFkhZh", 360 361 "9intrinsic5bswapFkZk", 361 362 "9intrinsic5outplFkkZk", 362 363 "9intrinsic5outpwFktZt", 363 364 #elif DMDV2 364 365 /* The names are mangled differently because of the pure and 365 366 * nothrow attributes. 366 367 */ 367 "4math3cosFNaNb eZe",368 "4math3sinFNaNb eZe",369 "4math4fabsFNaNb eZe",370 "4math4rintFNaNb eZe",371 "4math4sqrtFNaNb dZd",372 "4math4sqrtFNaNb eZe",373 "4math4sqrtFNaNb fZf",374 "4math4yl2xFNaNb eeZe",375 "4math5ldexpFNaNb eiZe",376 "4math6rndtolFNaNb eZl",377 "4math6yl2xp1FNaNb eeZe",368 "4math3cosFNaNbNfeZe", 369 "4math3sinFNaNbNfeZe", 370 "4math4fabsFNaNbNfeZe", 371 "4math4rintFNaNbNfeZe", 372 "4math4sqrtFNaNbNfdZd", 373 "4math4sqrtFNaNbNfeZe", 374 "4math4sqrtFNaNbNffZf", 375 "4math4yl2xFNaNbNfeeZe", 376 "4math5ldexpFNaNbNfeiZe", 377 "4math6rndtolFNaNbNfeZl", 378 "4math6yl2xp1FNaNbNfeeZe", 378 379 379 380 "9intrinsic2btFNaNbxPkkZi", 380 381 "9intrinsic3bsfFNaNbkZi", 381 382 "9intrinsic3bsrFNaNbkZi", 382 383 "9intrinsic3btcFNbPkkZi", 383 384 "9intrinsic3btrFNbPkkZi", 384 385 "9intrinsic3btsFNbPkkZi", 385 386 "9intrinsic3inpFNbkZh", 386 387 "9intrinsic4inplFNbkZk", 387 388 "9intrinsic4inpwFNbkZt", 388 389 "9intrinsic4outpFNbkhZh", 389 390 "9intrinsic5bswapFNaNbkZk", 390 391 "9intrinsic5outplFNbkkZk", 391 392 "9intrinsic5outpwFNbktZt", 392 393 #endif 393 394 }; 394 395 static const char *namearray64[] = 395 396 { 396 397 #if DMDV1 397 398 "4math3cosFeZe", 398 399 "4math3sinFeZe", 399 400 "4math4fabsFeZe", 400 401 "4math4rintFeZe", 401 402 "4math4sqrtFdZd", 402 403 "4math4sqrtFeZe", 403 404 "4math4sqrtFfZf", 404 405 "4math4yl2xFeeZe", 405 406 "4math5ldexpFeiZe", 406 407 "4math6rndtolFeZl", 407 408 "4math6yl2xp1FeeZe", 408 409 409 "9intrinsic2btFP kkZi",410 "9intrinsic2btFPmmZi", 410 411 "9intrinsic3bsfFkZi", 411 412 "9intrinsic3bsrFkZi", 412 413 "9intrinsic3btcFPmmZi", 413 414 "9intrinsic3btrFPmmZi", 414 415 "9intrinsic3btsFPmmZi", 415 416 "9intrinsic3inpFkZh", 416 417 "9intrinsic4inplFkZk", 417 418 "9intrinsic4inpwFkZt", 418 419 "9intrinsic4outpFkhZh", 419 420 "9intrinsic5bswapFkZk", 420 421 "9intrinsic5outplFkkZk", 421 422 "9intrinsic5outpwFktZt", 422 423 #elif DMDV2 423 424 /* The names are mangled differently because of the pure and 424 425 * nothrow attributes. 425 426 */ 426 "4math3cosFNaNb eZe",427 "4math3sinFNaNb eZe",428 "4math4fabsFNaNb eZe",429 "4math4rintFNaNb eZe",430 "4math4sqrtFNaNb dZd",431 "4math4sqrtFNaNb eZe",432 "4math4sqrtFNaNb fZf",433 "4math4yl2xFNaNb eeZe",434 "4math5ldexpFNaNb eiZe",435 "4math6rndtolFNaNb eZl",436 "4math6yl2xp1FNaNb eeZe",427 "4math3cosFNaNbNfeZe", 428 "4math3sinFNaNbNfeZe", 429 "4math4fabsFNaNbNfeZe", 430 "4math4rintFNaNbNfeZe", 431 "4math4sqrtFNaNbNfdZd", 432 "4math4sqrtFNaNbNfeZe", 433 "4math4sqrtFNaNbNffZf", 434 "4math4yl2xFNaNbNfeeZe", 435 "4math5ldexpFNaNbNfeiZe", 436 "4math6rndtolFNaNbNfeZl", 437 "4math6yl2xp1FNaNbNfeeZe", 437 438 438 439 "9intrinsic2btFNaNbxPkkZi", 439 440 "9intrinsic3bsfFNaNbkZi", 440 441 "9intrinsic3bsrFNaNbkZi", 441 442 "9intrinsic3btcFNbPmmZi", 442 443 "9intrinsic3btrFNbPmmZi", 443 444 "9intrinsic3btsFNbPmmZi", 444 445 "9intrinsic3inpFNbkZh", 445 446 "9intrinsic4inplFNbkZk", 446 447 "9intrinsic4inpwFNbkZt", 447 448 "9intrinsic4outpFNbkhZh", 448 449 "9intrinsic5bswapFNaNbkZk", 449 450 "9intrinsic5outplFNbkkZk", 450 451 "9intrinsic5outpwFNbktZt", 451 452 #endif 452 453 }; 453 454 static unsigned char ioptab[] = 454 455 { 455 456 OPcos, 456 457 OPsin, … … 521 522 * t1 Type of the array 522 523 * Output: 523 524 * e is rewritten to avoid side effects 524 525 * Returns: 525 526 * expression that initializes 'length' 526 527 */ 527 528 528 529 elem *resolveLengthVar(VarDeclaration *lengthVar, elem **pe, Type *t1) 529 530 { 530 531 //printf("resolveLengthVar()\n"); 531 532 elem *einit = NULL; 532 533 533 534 if (lengthVar && !(lengthVar->storage_class & STCconst)) 534 535 { elem *elength; 535 536 Symbol *slength; 536 537 537 538 if (t1->ty == Tsarray) 538 539 { TypeSArray *tsa = (TypeSArray *)t1; 539 540 dinteger_t length = tsa->dim->toInteger(); 540 541 541 elength = el_long(TY uint, length);542 elength = el_long(TYsize_t, length); 542 543 goto L3; 543 544 } 544 545 else if (t1->ty == Tarray) 545 546 { 546 547 elength = *pe; 547 548 *pe = el_same(&elength); 548 elength = el_una( OP64_32, TYuint, elength);549 elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elength); 549 550 550 551 L3: 551 552 slength = lengthVar->toSymbol(); 552 553 //symbol_add(slength); 553 554 554 einit = el_bin(OPeq, TY uint, el_var(slength), elength);555 einit = el_bin(OPeq, TYsize_t, el_var(slength), elength); 555 556 } 556 557 } 557 558 return einit; 558 559 } 559 560 560 561 /************************************* 561 562 * Closures are implemented by taking the local variables that 562 563 * need to survive the scope of the function, and copying them 563 564 * into a gc allocated chuck of memory. That chunk, called the 564 565 * closure here, is inserted into the linked list of stack 565 566 * frames instead of the usual stack frame. 566 567 * 567 568 * buildClosure() inserts code just after the function prolog 568 569 * is complete. It allocates memory for the closure, allocates 569 570 * a local variable (sclosure) to point to it, inserts into it 570 571 * the link to the enclosing frame, and copies into it the parameters 571 572 * that are referred to in nested functions. 572 573 * In VarExp::toElem and SymOffExp::toElem, when referring to a 573 574 * variable that is in a closure, takes the offset from sclosure rather 574 575 * than from the frame pointer. … … 596 597 * sthis 597 598 * ... closure variables ... 598 599 * ~this() { call destructor } 599 600 * } 600 601 */ 601 602 #endif 602 603 //printf("FuncDeclaration::buildClosure()\n"); 603 604 Symbol *sclosure; 604 605 sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype()); 605 606 sclosure->Sflags |= SFLtrue | SFLfree; 606 607 symbol_add(sclosure); 607 608 irs->sclosure = sclosure; 608 609 609 610 unsigned offset = PTRSIZE; // leave room for previous sthis 610 611 for (int i = 0; i < closureVars.dim; i++) 611 612 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; 612 613 assert(v->isVarDeclaration()); 613 614 614 615 #if DMDV2 615 616 if (v->needsAutoDtor()) 617 /* Because the value needs to survive the end of the scope! 618 */ 616 619 v->error("has scoped destruction, cannot build closure"); 620 if (v->isargptr) 621 /* See Bugzilla 2479 622 * This is actually a bug, but better to produce a nice 623 * message at compile time rather than memory corruption at runtime 624 */ 625 v->error("cannot reference variadic arguments from closure"); 617 626 #endif 618 627 /* Align and allocate space for v in the closure 619 628 * just like AggregateDeclaration::addField() does. 620 629 */ 621 630 unsigned memsize; 622 631 unsigned memalignsize; 623 632 unsigned xalign; 624 633 #if DMDV2 625 634 if (v->storage_class & STClazy) 626 635 { 627 636 /* Lazy variables are really delegates, 628 637 * so give same answers that TypeDelegate would 629 638 */ 630 639 memsize = PTRSIZE * 2; 631 640 memalignsize = memsize; 632 641 xalign = global.structalign; 633 642 } 643 else if (v->isRef() || v->isOut()) 644 { // reference parameters are just pointers 645 memsize = PTRSIZE; 646 memalignsize = memsize; 647 xalign = global.structalign; 648 } 634 649 else 635 650 #endif 636 651 { 637 652 memsize = v->type->size(); 638 653 memalignsize = v->type->alignsize(); 639 654 xalign = v->type->memalign(global.structalign); 640 655 } 641 656 AggregateDeclaration::alignmember(xalign, memalignsize, &offset); 642 657 v->offset = offset; 643 658 offset += memsize; 644 659 645 660 /* Can't do nrvo if the variable is put in a closure, since 646 661 * what the shidden points to may no longer exist. 647 662 */ 648 663 if (nrvo_can && nrvo_var == v) 649 664 { 650 665 nrvo_can = 0; 651 666 } 652 667 } 653 668 // offset is now the size of the closure 654 669 655 670 // Allocate memory for the closure 656 671 elem *e; 657 e = el_long(TY int, offset);672 e = el_long(TYsize_t, offset); 658 673 e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e); 659 674 660 675 // Assign block of memory to sclosure 661 676 // sclosure = allocmemory(sz); 662 677 e = el_bin(OPeq, TYvoid, el_var(sclosure), e); 663 678 664 679 // Set the first element to sthis 665 680 // *(sclosure + 0) = sthis; 666 681 elem *ethis; 667 682 if (irs->sthis) 668 683 ethis = el_var(irs->sthis); 669 684 else 670 685 ethis = el_long(TYnptr, 0); 671 686 elem *ex = el_una(OPind, TYnptr, el_var(sclosure)); 672 687 ex = el_bin(OPeq, TYnptr, ex, ethis); 673 688 e = el_combine(e, ex); 674 689 675 690 // Copy function parameters into closure 676 691 for (int i = 0; i < closureVars.dim; i++) 677 692 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; 678 693 679 694 if (!v->isParameter()) 680 695 continue; 681 696 tym_t tym = v->type->totym(); 682 697 if (v->type->toBasetype()->ty == Tsarray || v->isOut() || v->isRef()) 683 698 tym = TYnptr; // reference parameters are just pointers 684 699 #if DMDV2 685 700 else if (v->storage_class & STClazy) 686 701 tym = TYdelegate; 687 702 #endif 688 ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TY int, v->offset));703 ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYsize_t, v->offset)); 689 704 ex = el_una(OPind, tym, ex); 690 if ( ex->Ety== TYstruct)705 if (tybasic(ex->Ety) == TYstruct) 691 706 { 692 707 ::type *t = v->type->toCtype(); 693 708 ex->ET = t; 694 709 ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol())); 695 710 ex->ET = t; 696 711 } 697 712 else 698 713 ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol())); 699 714 700 715 e = el_combine(e, ex); 701 716 } 702 717 703 718 block_appendexp(irs->blx->curblock, e); 704 719 } 705 720 } 706 721 707 722 #endif 708 723 709 724 /*************************** 710 725 * Determine return style of function - whether in registers or trunk/src/backend/cg87.c
r720 r767 2908 2908 // fldcw roundto0 2909 2909 // fistp long64 ptr [ESP] 2910 2910 // fldcw 8[ESP] 2911 2911 // pop lsw 2912 2912 // pop msw 2913 2913 // add ESP,4 2914 2914 2915 2915 unsigned szpush = szoff + 2; 2916 2916 if (config.flags3 & CFG3pic) 2917 2917 szpush += 2; 2918 2918 szpush = (szpush + REGSIZE - 1) & ~(REGSIZE - 1); 2919 2919 2920 2920 retregs = mST0; 2921 2921 c1 = codelem(e->E1,&retregs,FALSE); 2922 2922 2923 2923 if (szpush == REGSIZE) 2924 2924 c1 = gen1(c1,0x50 + AX); // PUSH EAX 2925 2925 else 2926 2926 c1 = genc2(c1,0x81,grex | modregrm(3,5,SP), szpush); // SUB ESP,12 2927 2927 c1 = genfwait(c1); 2928 genc1(c1,0xD9, grex |modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP]2928 genc1(c1,0xD9,modregrm(2,7,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FSTCW szoff[ESP] 2929 2929 2930 2930 c1 = genfwait(c1); 2931 2931 2932 2932 if (config.flags3 & CFG3pic) 2933 2933 { 2934 genc(c1,0xC7, grex |modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto02934 genc(c1,0xC7,modregrm(2,0,4) + 256*modregrm(0,4,SP),FLconst,szoff+2,FLconst,CW_roundto0); // MOV szoff+2[ESP], CW_roundto0 2935 2935 code_orflag(c1, CFopsize); 2936 genc1(c1,0xD9, grex |modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP]2936 genc1(c1,0xD9,modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff+2); // FLDCW szoff+2[ESP] 2937 2937 } 2938 2938 else 2939 2939 c1 = genrnd(c1, CW_roundto0); // FLDCW roundto0 2940 2940 2941 2941 pop87(); 2942 2942 2943 2943 c1 = genfwait(c1); 2944 2944 gen2sib(c1,mf,grex | modregrm(0,rf,4),modregrm(0,4,SP)); // FISTP [ESP] 2945 2945 2946 2946 retregs = *pretregs & (ALLREGS | mBP); 2947 2947 if (!retregs) 2948 2948 retregs = ALLREGS; 2949 2949 c2 = allocreg(&retregs,®,tym); 2950 2950 2951 2951 c2 = genfwait(c2); // FWAIT 2952 2952 c2 = genc1(c2,0xD9,grex | modregrm(2,5,4) + 256*modregrm(0,4,SP),FLconst,szoff); // FLDCW szoff[ESP] 2953 2953 2954 2954 if (szoff > REGSIZE) 2955 2955 { szpush -= REGSIZE; 2956 2956 c2 = genpop(c2,findreglsw(retregs)); // POP lsw trunk/src/backend/cgcod.c
r738 r767 1090 1090 goto L2; 1091 1091 1092 1092 case BC_try: 1093 1093 if (config.flags2 & CFG2seh) 1094 1094 { usednteh |= NTEH_try; 1095 1095 nteh_usevars(); 1096 1096 } 1097 1097 else 1098 1098 usednteh |= EHtry; 1099 1099 goto case_goto; 1100 1100 1101 1101 case BC_finally: 1102 1102 // Mark all registers as destroyed. This will prevent 1103 1103 // register assignments to variables used in finally blocks. 1104 1104 assert(!getregs(allregs)); 1105 1105 assert(!e); 1106 1106 assert(!bl->Bcode); 1107 1107 #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS 1108 1108 if (config.flags3 & CFG3pic) 1109 1109 { 1110 int nalign = 0; 1110 1111 if (STACKALIGN == 16) 1111 { c = genc2(c,0x81,modregrm(3,5,SP),12); // SUB ESP,12 1112 { nalign = STACKALIGN - REGSIZE; 1113 c = genc2(c,0x81,modregrm(3,5,SP),nalign); // SUB ESP,nalign 1112 1114 if (I64) 1113 1115 code_orrex(c, REX_W); 1114 1116 } 1115 1117 // CALL bl->Bsucc 1116 1118 c = genc(c,0xE8,0,0,0,FLblock,(long)list_block(bl->Bsucc)); 1117 if ( STACKALIGN == 16)1118 { c = genc2(c,0x81,modregrm(3,0,SP), 12); // ADD ESP,121119 if (nalign) 1120 { c = genc2(c,0x81,modregrm(3,0,SP),nalign); // ADD ESP,nalign 1119 1121 if (I64) 1120 1122 code_orrex(c, REX_W); 1121 1123 } 1122 1124 // JMP list_next(bl->Bsucc) 1123 1125 nextb = list_block(list_next(bl->Bsucc)); 1124 1126 goto L2; 1125 1127 } 1126 1128 else 1127 1129 #endif 1128 1130 { 1129 1131 // Generate a PUSH of the address of the successor to the 1130 1132 // corresponding BC_ret 1131 1133 //assert(list_block(list_next(bl->Bsucc))->BC == BC_ret); 1132 1134 // PUSH &succ 1133 1135 c = genc(c,0x68,0,0,0,FLblock,(long)list_block(list_next(bl->Bsucc))); 1134 1136 nextb = list_block(bl->Bsucc); 1135 1137 goto L2; 1136 1138 } 1137 1139 1138 1140 case BC_ret: trunk/src/backend/cgelem.c
r738 r767 4137 4137 4138 4138 STATIC elem * elarray(elem *e) 4139 4139 { 4140 4140 return e; 4141 4141 } 4142 4142 4143 4143 /******************************************** 4144 4144 */ 4145 4145 4146 4146 STATIC elem * elfield(elem *e) 4147 4147 { 4148 4148 return e; 4149 4149 } 4150 4150 4151 4151 /****************************************** 4152 4152 * OPparam 4153 4153 */ 4154 4154 4155 4155 STATIC void elparamx(elem *e) 4156 4156 { 4157 elem *ex;4158 4159 4157 //printf("elparam()\n"); 4160 4158 if (e->E1->Eoper == OPrpair) 4161 4159 { 4162 4160 e->E1->Eoper = OPparam; 4163 4161 } 4164 4162 else if (e->E1->Eoper == OPpair && !el_sideeffect(e->E1)) 4165 4163 { 4166 4164 e->E1->Eoper = OPparam; 4167 e x = e->E1->E2;4165 elem *ex = e->E1->E2; 4168 4166 e->E1->E2 = e->E1->E1; 4169 4167 e->E1->E1 = ex; 4170 4168 } 4171 4169 #if 0 4172 4170 // Unfortunately, these don't work because if the last parameter 4173 4171 // is a pair, and it is a D function, the last parameter will get 4174 4172 // passed in EAX. 4175 4173 else if (e->E2->Eoper == OPrpair) 4176 4174 { 4177 4175 e->E2->Eoper = OPparam; 4178 4176 } 4179 4177 else if (e->E2->Eoper == OPpair) 4180 4178 { 4181 4179 e->E2->Eoper = OPparam; 4182 e x = e->E2->E2;4180 elem *ex = e->E2->E2; 4183 4181 e->E2->E2 = e->E2->E1; 4184 4182 e->E2->E1 = ex; 4185 4183 } 4186 4184 #endif 4187 4185 } 4188 4186 4189 4187 STATIC elem * elparam(elem *e) 4190 4188 { 4191 4189 if (!OPTIMIZER) 4192 4190 { 4193 4191 if (!I64) 4194 4192 elparamx(e); 4195 4193 } 4196 4194 return e; 4197 4195 } 4198 4196 4199 4197 /******************************** 4200 4198 * Optimize an element. This routine is recursive! 4201 4199 * Be careful not to do this if VBEs have been done (else the VBE 4202 4200 * work will be undone), or it DAGs have been built (will crash if … … 4690 4688 { 4691 4689 error(filename, linnum, "null dereference in function %s", funcsym_p->Sident); 4692 4690 e->E1->EV.Vlong = 4096; // suppress redundant messages 4693 4691 } 4694 4692 #endif 4695 4693 } 4696 4694 e = e->E1; 4697 4695 } 4698 4696 else if (OTbinary(e->Eoper)) 4699 4697 { 4700 4698 #if MARS 4701 4699 /* This is necessary as the optimizer tends to lose this information 4702 4700 */ 4703 4701 if (e->Esrcpos.Slinnum > linnum) 4704 4702 { linnum = e->Esrcpos.Slinnum; 4705 4703 filename = e->Esrcpos.Sfilename; 4706 4704 } 4707 4705 #endif 4708 4706 if (e->Eoper == OPparam) 4709 4707 { 4710 elparamx(e); 4708 if (!I64) 4709 elparamx(e); 4711 4710 } 4712 4711 postoptelem(e->E2); 4713 4712 e = e->E1; 4714 4713 } 4715 4714 else 4716 4715 break; 4717 4716 } 4718 4717 } 4719 4718 4720 4719 #endif // !SPP trunk/src/backend/cod1.c
r738 r767 956 956 { t = 0; 957 957 rbase = 5; 958 958 } 959 959 else 960 960 { t = 0; 961 961 rbase = reg; 962 962 if (rbase == BP) 963 963 { static unsigned imm32[4] = {1+1,2+1,4+1,8+1}; 964 964 965 965 // IMUL r,BP,imm32 966 966 c = genc2(c,0x69,modregxrm(3,r,BP),imm32[ss1]); 967 967 goto L7; 968 968 } 969 969 } 970 970 971 971 c = gen2sib(c,0x8D,modregxrm(t,r,4),modregrm(ss1,reg & 7,rbase & 7)); 972 972 if (reg & 8) 973 973 code_orrex(c, REX_X); 974 974 if (rbase & 8) 975 975 code_orrex(c, REX_B); 976 if (I64) 977 code_orrex(c, REX_W); 976 978 977 979 if (ssflags & SSFLnobase1) 978 980 { code_last(c)->IFL1 = FLconst; 979 981 code_last(c)->IEV1.Vuns = 0; 980 982 } 981 983 L7: 982 984 if (ssflags & SSFLnobase) 983 985 { t = stackfl[f] ? 2 : 0; 984 986 rbase = 5; 985 987 } 986 988 else 987 989 { t = 2; 988 990 rbase = r; 989 991 assert(rbase != BP); 990 992 } 991 993 pcs->Irm = modregrm(t,0,4); 992 994 pcs->Isib = modregrm(ssindex_array[ssi].ss2,r & 7,rbase & 7); 993 995 if (r & 8) 994 996 code_orrex(pcs, REX_X); 995 997 if (rbase & 8) … … 1066 1068 c = cat(c,allocreg(&idxregs,®,TYoffset)); 1067 1069 1068 1070 /* If desired result is a far pointer, we'll have */ 1069 1071 /* to load another register with the segment of v */ 1070 1072 if (e1ty == TYfptr) 1071 1073 { 1072 1074 unsigned msreg; 1073 1075 1074 1076 idxregs |= mMSW & ALLREGS & ~keepmsk; 1075 1077 c = cat(c,allocreg(&idxregs,&msreg,TYfptr)); 1076 1078 msreg = findregmsw(idxregs); 1077 1079 /* MOV msreg,segreg */ 1078 1080 c = genregs(c,0x8C,segfl[f],msreg); 1079 1081 } 1080 1082 opsave = pcs->Iop; 1081 1083 flagsave = pcs->Iflags; 1082 1084 pcs->Iop = 0x8D; 1083 1085 code_newreg(pcs, reg); 1084 1086 if (!I16) 1085 1087 pcs->Iflags &= ~CFopsize; 1088 if (I64) 1089 pcs->Irex |= REX_W; 1086 1090 c = gen(c,pcs); /* LEA idxreg,EA */ 1087 1091 cssave(e1,idxregs,TRUE); 1088 1092 if (!I16) 1089 1093 pcs->Iflags = flagsave; 1090 1094 if (stackfl[f] && (config.wflags & WFssneds)) // if pointer into stack 1091 1095 pcs->Iflags |= CFss; // add SS: override 1092 1096 pcs->Iop = opsave; 1093 1097 pcs->IFL1 = FLoffset; 1094 1098 pcs->IEV1.Vuns = 0; 1095 1099 setaddrmode(pcs, idxregs); 1096 1100 } 1097 1101 freenode(e12); 1098 1102 if (e1free) 1099 1103 freenode(e1); 1100 1104 goto Lptr; 1101 1105 } 1102 1106 1103 1107 L1: 1104 1108 1105 1109 /* The rest of the cases could be a far pointer */ … … 2846 2850 { unsigned lsreg; 2847 2851 LF1: 2848 2852 reg = findregmsw(retregs); 2849 2853 lsreg = findreglsw(retregs); 2850 2854 floatreg = TRUE; /* use float register */ 2851 2855 reflocal = TRUE; 2852 2856 ce = genc1(ce,0x89, /* MOV floatreg+2,reg */ 2853 2857 modregrm(2,reg,BPRM),FLfltreg,REGSIZE); 2854 2858 genc1(ce,0x89, /* MOV floatreg,lsreg */ 2855 2859 modregrm(2,lsreg,BPRM),FLfltreg,0); 2856 2860 if (tym1 == TYifunc) 2857 2861 gen1(ce,0x9C); // PUSHF 2858 2862 genc1(ce,0xFF, /* CALL [floatreg] */ 2859 2863 modregrm(2,3,BPRM),FLfltreg,0); 2860 2864 } 2861 2865 else 2862 2866 { 2863 2867 LF2: 2864 2868 reg = findreg(retregs); 2865 2869 ce = gen2(ce,0xFF,modregrmx(3,2,reg)); /* CALL reg */ 2870 if (I64) 2871 code_orrex(ce, REX_W); 2866 2872 } 2867 2873 } 2868 2874 else 2869 2875 { 2870 2876 if (tym1 == TYifunc) 2871 2877 c = gen1(c,0x9C); // PUSHF 2872 2878 // CALL [function] 2873 2879 cs.Iflags = 0; 2874 2880 cgstate.stackclean++; 2875 2881 ce = loadea(e11,&cs,0xFF,farfunc ? 3 : 2,0,keepmsk,(ALLREGS|mES|mBP) & ~fregsaved); 2876 2882 cgstate.stackclean--; 2877 2883 freenode(e11); 2878 2884 } 2879 2885 s = NULL; 2880 2886 } 2881 2887 c = cat(c,ce); 2882 2888 freenode(e1); 2883 2889 2884 2890 /* See if we will need the frame pointer. 2885 2891 Calculate it here so we can possibly use BP to fix the stack. trunk/src/backend/cod2.c
r738 r767 636 636 } 637 637 } 638 638 rval = reghasvalue(byte ? BYTEREGS : ALLREGS,i,&rreg); 639 639 cs.IEV2.Vint = i; 640 640 L3: 641 641 op1 ^= byte; 642 642 cs.Iflags |= word; 643 643 if (rval) 644 644 { cs.Iop = op1 ^ 2; 645 645 mode = rreg; 646 646 } 647 647 else 648 648 cs.Iop = 0x81; 649 649 cs.Irm = modregrm(3,mode&7,reg&7); 650 650 if (mode & 8) 651 651 cs.Irex |= REX_R; 652 652 if (reg & 8) 653 653 cs.Irex |= REX_B; 654 654 if (I64 && sz == 8) 655 655 cs.Irex |= REX_W; 656 if (I64 && byte && reg >= 4) 657 cs.Irex |= REX; 656 658 cs.IFL2 = (e2->Eoper == OPconst) ? FLconst : el_fl(e2); 657 659 /* Modify instruction for special cases */ 658 660 switch (e->Eoper) 659 661 { case OPadd: 660 662 { int iop; 661 663 662 664 if (i == 1) 663 665 iop = 0; /* INC reg */ 664 666 else if (i == -1) 665 667 iop = 8; /* DEC reg */ 666 668 else 667 669 break; 668 670 cs.Iop = (0x40 | iop | reg) ^ byte; 669 671 if ((byte && *pretregs & mPSW) || I64) 670 672 { cs.Irm = modregrm(3,0,reg & 7) | iop; 671 673 cs.Iop = 0xFF; 672 674 } 673 675 break; 674 676 } 675 677 case OPand: … … 3294 3296 c2->Iflags = CFopsize; 3295 3297 offset += 2; 3296 3298 c3 = cat(c3,c2); 3297 3299 } 3298 3300 if (numbytes & 1) 3299 3301 { // MOV byte ptr offset[reg],vreg 3300 3302 c2 = gen2(CNIL,0x88,modregxrmx(2,vreg,reg)); 3301 3303 c2->IEVoffset1 = offset; 3302 3304 c2->IFL1 = FLconst; 3303 3305 c3 = cat(c3,c2); 3304 3306 } 3305 3307 fixres: 3306 3308 return cat3(c1,c3,fixresult(e,retregs1,pretregs)); 3307 3309 } 3308 3310 } 3309 3311 3310 3312 // Get nbytes into CX 3311 3313 retregs2 = mCX; 3312 3314 if (!I16 && e2->E1->Eoper == OPconst && e2->E2->Eoper == OPconst) 3313 3315 { 3314 remainder = numbytes & ( REGSIZE- 1);3315 numwords = numbytes / REGSIZE;// number of words3316 remainder = numbytes & (4 - 1); 3317 numwords = numbytes / 4; // number of words 3316 3318 op = 0xAB; // moving by words 3317 3319 c1 = getregs(mCX); 3318 3320 c1 = movregconst(c1,CX,numwords,I64?64:0); // # of bytes/words 3319 3321 } 3320 3322 else 3321 3323 { 3322 3324 remainder = 0; 3323 3325 op = 0xAA; // must move by bytes 3324 3326 c1 = codelem(e2->E1,&retregs2,FALSE); 3325 3327 } 3326 3328 3327 3329 // Get val into AX 3328 3330 3329 3331 retregs3 = mAX; 3330 3332 if (!I16 && e2->E2->Eoper == OPconst) 3331 3333 { 3332 3334 c1 = regwithvalue(c1, mAX, value, NULL, I64?64:0); 3333 3335 freenode(e2->E2); 3334 3336 } 3335 3337 else trunk/src/backend/cod3.c
r760 r767 2287 2287 2288 2288 /* Skip over return address */ 2289 2289 thunkty = tybasic(sthunk->ty()); 2290 2290 if (tyfarfunc(thunkty)) 2291 2291 p += I32 ? 8 : tysize[TYfptr]; /* far function */ 2292 2292 else 2293 2293 p += tysize[TYnptr]; 2294 2294 2295 2295 if (!I16) 2296 2296 { 2297 2297 /* 2298 2298 Generate: 2299 2299 ADD p[ESP],d 2300 2300 For direct call: 2301 2301 JMP sfunc 2302 2302 For virtual call: 2303 2303 MOV EAX, p[ESP] EAX = this 2304 2304 MOV EAX, d2[EAX] EAX = this->vptr 2305 2305 JMP i[EAX] jump to virtual function 2306 2306 */ 2307 unsigned reg = 0; 2308 if ((targ_ptrdiff_t)d < 0) 2309 { 2310 d = -d; 2311 reg = 5; // switch from ADD to SUB 2312 } 2307 2313 if (thunkty == TYmfunc) 2308 2314 { // ADD ECX,d 2309 2315 c = CNIL; 2310 2316 if (d) 2311 c = genc2(c,0x81,modregrm(3, 0,CX),d);2317 c = genc2(c,0x81,modregrm(3,reg,CX),d); 2312 2318 } 2313 2319 else if (thunkty == TYjfunc) 2314 2320 { // ADD EAX,d 2315 2321 c = CNIL; 2316 2322 if (d) 2317 c = genc2(c,0x81,modregrm(3, 0,AX),d);2323 c = genc2(c,0x81,modregrm(3,reg,I64 ? DI : AX),d); 2318 2324 } 2319 2325 else 2320 2326 { 2321 c = genc(CNIL,0x81,modregrm(2, 0,4),2327 c = genc(CNIL,0x81,modregrm(2,reg,4), 2322 2328 FLconst,p, // to this 2323 2329 FLconst,d); // ADD p[ESP],d 2324 2330 c->Isib = modregrm(0,4,SP); 2325 2331 } 2326 2332 if (I64) 2327 2333 c->Irex |= REX_W; 2328 2334 } 2329 2335 else 2330 2336 { 2331 2337 /* 2332 2338 Generate: 2333 2339 MOV BX,SP 2334 2340 ADD [SS:] p[BX],d 2335 2341 For direct call: 2336 2342 JMP sfunc 2337 2343 For virtual call: 2338 2344 MOV BX, p[BX] BX = this 2339 2345 MOV BX, d2[BX] BX = this->vptr 2340 2346 JMP i[BX] jump to virtual function 2341 2347 */ … … 4552 4558 case FLfunc: /* function call */ 4553 4559 s = uev->sp.Vsym; /* symbol pointer */ 4554 4560 #if !TARGET_FLAT 4555 4561 if (tyfarfunc(s->ty())) 4556 4562 { /* Large code references are always absolute */ 4557 4563 FLUSH(); 4558 4564 offset += reftoident(cseg,offset,s,0,flags) - 4; 4559 4565 } 4560 4566 else if (s->Sseg == cseg && 4561 4567 (s->Sclass == SCstatic || s->Sclass == SCglobal) && 4562 4568 s->Sxtrnnum == 0 && flags & CFselfrel) 4563 4569 { /* if we know it's relative address */ 4564 4570 ad = s->Soffset - OFFSET() - 4; 4565 4571 goto L1; 4566 4572 } 4567 4573 else 4568 4574 #endif 4569 4575 { 4570 4576 assert(!(TARGET_FLAT && tyfarfunc(s->ty()))); 4571 4577 FLUSH(); 4572 reftoident(cseg,offset,s, 0,flags);4578 reftoident(cseg,offset,s,val,flags); 4573 4579 } 4574 4580 break; 4575 4581 4576 4582 case FLblock: /* displacement to another block */ 4577 4583 ad = uev->Vblock->Boffset - OFFSET() - 4; 4578 4584 //printf("FLblock: funcoffset = %x, OFFSET = %x, Boffset = %x, ad = %x\n", funcoffset, OFFSET(), uev->Vblock->Boffset, ad); 4579 4585 goto L1; 4580 4586 4581 4587 case FLblockoff: 4582 4588 FLUSH(); 4583 4589 assert(uev->Vblock); 4584 4590 //printf("FLblockoff: offset = %x, Boffset = %x, funcoffset = %x\n", offset, uev->Vblock->Boffset, funcoffset); 4585 4591 reftocodseg(cseg,offset,uev->Vblock->Boffset); 4586 4592 break; 4587 4593 4588 4594 default: 4589 4595 #ifdef DEBUG 4590 4596 WRFL(fl); 4591 4597 #endif 4592 4598 assert(0); trunk/src/backend/cod4.c
r738 r767 1006 1006 cs.Iop = op1 ^ 2; // toggle direction bit 1007 1007 if (forccs) 1008 1008 cs.Iflags |= CFpsw; 1009 1009 reverse = 2; // remember we toggled it 1010 1010 cl = gen(cl,&cs); 1011 1011 c = cat(cr,cl); 1012 1012 retregs = 0; /* to trigger a bug if we attempt to use it */ 1013 1013 } 1014 1014 else // evaluate e2 into register 1015 1015 { 1016 1016 retregs = (byte) ? BYTEREGS : ALLREGS; // pick working reg 1017 1017 if (tyml == TYhptr) 1018 1018 retregs &= ~mCX; // need CX for shift count 1019 1019 cr = scodelem(e->E2,&retregs,0,TRUE); // get rvalue 1020 1020 cl = getlvalue(&cs,e1,retregs); // get lvalue 1021 1021 cl = cat(cl,modEA(&cs)); 1022 1022 cs.Iop = op1; 1023 1023 if (sz <= REGSIZE || tyfv(tyml)) 1024 1024 { reg = findreg(retregs); 1025 1025 code_newreg(&cs, reg); // OP1 EA,reg 1026 if (sz == 1 && reg >= 4 && I64) 1027 cs.Irex |= REX; 1026 1028 } 1027 1029 else if (tyml == TYhptr) 1028 1030 { unsigned mreg,lreg; 1029 1031 1030 1032 mreg = findregmsw(retregs); 1031 1033 lreg = findreglsw(retregs); 1032 1034 cl = cat(cl,getregs(retregs | mCX)); 1033 1035 1034 1036 // If h -= l, convert to h += -l 1035 1037 if (e->Eoper == OPminass) 1036 1038 { 1037 1039 cl = gen2(cl,0xF7,modregrm(3,3,mreg)); // NEG mreg 1038 1040 gen2(cl,0xF7,modregrm(3,3,lreg)); // NEG lreg 1039 1041 code_orflag(cl,CFpsw); 1040 1042 genc2(cl,0x81,modregrm(3,3,mreg),0); // SBB mreg,0 1041 1043 } 1042 1044 cs.Iop = 0x01; 1043 1045 cs.Irm |= modregrm(0,lreg,0); 1044 1046 cl = gen(cl,&cs); // ADD EA,lreg 1045 1047 code_orflag(cl,CFpsw); trunk/src/backend/elfobj.c
r714 r767 2752 2752 if (s->Sclass == SCstatic) 2753 2753 relinfo = RI_TYPE_TLS_LE; // TLS_GD? 2754 2754 else 2755 2755 relinfo = RI_TYPE_TLS_IE; 2756 2756 } 2757 2757 else 2758 2758 { 2759 2759 if (s->Sclass == SCstatic) 2760 2760 relinfo = RI_TYPE_TLS_LE; 2761 2761 else 2762 2762 relinfo = RI_TYPE_TLS_IE; 2763 2763 } 2764 2764 } 2765 2765 } 2766 2766 if (flags & CFoffset64 && relinfo == R_X86_64_32) 2767 2767 { 2768 2768 relinfo = R_X86_64_64; 2769 2769 } 2770 2770 //printf("\t\t************* adding relocation\n"); 2771 2771 targ_size_t v = 0; 2772 if (I64 && re linfo == R_X86_64_PC32)2772 if (I64 && retsize == 4) 2773 2773 { 2774 2774 assert(retsize == 4); 2775 2775 if (val > 0xFFFFFFFF) 2776 2776 { /* The value to be added is bigger than 32 bits, so we 2777 2777 * transfer it to the 64 bit addend of the fixup record 2778 2778 */ 2779 2779 v = val; 2780 2780 val = 0; 2781 2781 } 2782 2782 } 2783 2783 #if 0 2784 2784 targ_size_t v = (relinfo == R_X86_64_PC32) ? -4 : 0; 2785 2785 if (relinfo == R_X86_64_PC32 && flags & CFaddend8) 2786 2786 v = -8; 2787 2787 #endif 2788 2788 elf_addrel(seg,offset,relinfo,refseg,v); 2789 2789 } 2790 2790 outaddrval: 2791 2791 if (retsize == 8) 2792 2792 buf->write64(val); … … 2990 2990 if (I64) 2991 2991 buf->writeByte(REX | REX_W); 2992 2992 buf->writeByte(0x8B); buf->writeByte(0x11); /* movl (%ecx), %edx */ 2993 2993 if (I64) 2994 2994 buf->writeByte(REX | REX_W); 2995 2995 buf->writeByte(0x89); buf->writeByte(0x10); /* movl %edx, (%eax) */ 2996 2996 if (I64) 2997 2997 buf->writeByte(REX | REX_W); 2998 2998 buf->writeByte(0x89); buf->writeByte(0x01); /* movl %eax, (%ecx) */ 2999 2999 3000 3000 if (I32) buf->writeByte(0x61); // POPAD 3001 3001 buf->writeByte(0xC3); /* ret */ 3002 3002 SegData[seg]->SDoffset = buf->size(); 3003 3003 } 3004 3004 3005 3005 /* Add reference to constructor into ".ctors" segment 3006 3006 */ 3007 3007 const int seg = elf_getsegment(".ctors", NULL, SHT_PROGDEF, SHF_ALLOC|SHF_WRITE, NPTRSIZE); 3008 3008 3009 3009 Outbuffer *buf = SegData[seg]->SDbuf; 3010 buf->write32(codeOffset); 3010 if (I64) 3011 buf->write64(codeOffset); 3012 else 3013 buf->write32(codeOffset); 3011 3014 elf_addrel(seg, SegData[seg]->SDoffset, I64 ? R_X86_64_64 : RI_TYPE_SYM32, STI_TEXT, 0); 3012 3015 SegData[seg]->SDoffset += NPTRSIZE; 3013 3016 } 3014 3017 3015 3018 #endif 3016 3019 3017 3020 /************************************* 3018 3021 */ 3019 3022 3020 3023 void elfobj_gotref(symbol *s) 3021 3024 { 3022 3025 //printf("elfobj_gotref(%x '%s', %d)\n",s,s->Sident, s->Sclass); 3023 3026 switch(s->Sclass) 3024 3027 { 3025 3028 case SCstatic: 3026 3029 case SClocstat: 3027 3030 s->Sfl = FLgotoff; 3028 3031 break; 3029 3032 3030 3033 case SCextern: trunk/src/backend/rtlsym.h
r738 r767 47 47 SYMBOL_MARS(MONITOR_PROLOG, FLfunc,FREGSAVED,"_d_monitor_prolog",0,t) \ 48 48 SYMBOL_MARS(MONITOR_EPILOG, FLfunc,FREGSAVED,"_d_monitor_epilog",0,t) \ 49 49 SYMBOL_MARS(DCOVER, FLfunc,FREGSAVED,"_d_cover_register", 0, t) \ 50 50 SYMBOL_MARS(DASSERT, FLfunc,FREGSAVED,"_d_assert", SFLexit, t) \ 51 51 SYMBOL_MARS(DASSERTM, FLfunc,FREGSAVED,"_d_assertm", SFLexit, t) \ 52 52 SYMBOL_MARS(DASSERT_MSG, FLfunc,FREGSAVED,"_d_assert_msg", SFLexit, t) \ 53 53 SYMBOL_MARS(DUNITTEST, FLfunc,FREGSAVED,"_d_unittest", 0, t) \ 54 54 SYMBOL_MARS(DUNITTESTM, FLfunc,FREGSAVED,"_d_unittestm", 0, t) \ 55 55 SYMBOL_MARS(DUNITTEST_MSG, FLfunc,FREGSAVED,"_d_unittest_msg", 0, t) \ 56 56 SYMBOL_MARS(DARRAY, FLfunc,FREGSAVED,"_d_array_bounds", SFLexit, t) \ 57 57 SYMBOL_MARS(DINVARIANT, FLfunc,FREGSAVED,"D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \ 58 58 SYMBOL_MARS(_DINVARIANT, FLfunc,FREGSAVED,"_D9invariant12_d_invariantFC6ObjectZv", 0, tsdlib) \ 59 59 SYMBOL_MARS(MEMCPY, FLfunc,FREGSAVED,"memcpy", 0, t) \ 60 60 SYMBOL_MARS(MEMSET8, FLfunc,FREGSAVED,"memset", 0, t) \ 61 61 SYMBOL_MARS(MEMSET16, FLfunc,FREGSAVED,"_memset16", 0, t) \ 62 62 SYMBOL_MARS(MEMSET32, FLfunc,FREGSAVED,"_memset32", 0, t) \ 63 63 SYMBOL_MARS(MEMSET64, FLfunc,FREGSAVED,"_memset64", 0, t) \ 64 64 SYMBOL_MARS(MEMSET128, FLfunc,FREGSAVED,"_memset128",0, t) \ 65 65 SYMBOL_MARS(MEMSET80, FLfunc,FREGSAVED,"_memset80", 0, t) \ 66 66 SYMBOL_MARS(MEMSET160, FLfunc,FREGSAVED,"_memset160",0, t) \ 67 SYMBOL_MARS(MEMSETFLOAT, FLfunc,FREGSAVED,"_memsetFloat", 0, t) \ 68 SYMBOL_MARS(MEMSETDOUBLE, FLfunc,FREGSAVED,"_memsetDouble", 0, t) \ 67 69 SYMBOL_MARS(MEMSETN, FLfunc,FREGSAVED,"_memsetn", 0, t) \ 68 70 SYMBOL_MARS(MODULO, FLfunc,FREGSAVED,"_modulo", 0, t) \ 69 71 SYMBOL_MARS(MONITORENTER, FLfunc,FREGSAVED,"_d_monitorenter",0, t) \ 70 72 SYMBOL_MARS(MONITOREXIT, FLfunc,FREGSAVED,"_d_monitorexit",0, t) \ 71 73 SYMBOL_MARS(CRITICALENTER, FLfunc,FREGSAVED,"_d_criticalenter",0, t) \ 72 74 SYMBOL_MARS(CRITICALEXIT, FLfunc,FREGSAVED,"_d_criticalexit",0, t) \ 73 75 SYMBOL_MARS(SWITCH_STRING, FLfunc,FREGSAVED,"_d_switch_string", 0, t) \ 74 76 SYMBOL_MARS(SWITCH_USTRING,FLfunc,FREGSAVED,"_d_switch_ustring", 0, t) \ 75 77 SYMBOL_MARS(SWITCH_DSTRING,FLfunc,FREGSAVED,"_d_switch_dstring", 0, t) \ 76 78 SYMBOL_MARS(DSWITCHERR, FLfunc,FREGSAVED,"_d_switch_error", SFLexit, t) \ 77 79 SYMBOL_MARS(DHIDDENFUNC, FLfunc,FREGSAVED,"_d_hidden_func", 0, t) \ 78 80 SYMBOL_MARS(NEWCLASS, FLfunc,FREGSAVED,"_d_newclass", 0, t) \ 79 81 SYMBOL_MARS(NEWARRAYT, FLfunc,FREGSAVED,"_d_newarrayT", 0, t) \ 80 82 SYMBOL_MARS(NEWARRAYIT, FLfunc,FREGSAVED,"_d_newarrayiT", 0, t) \ 81 83 SYMBOL_MARS(NEWARRAYMT, FLfunc,FREGSAVED,"_d_newarraymT", 0, tv) \ 82 84 SYMBOL_MARS(NEWARRAYMIT, FLfunc,FREGSAVED,"_d_newarraymiT", 0, tv) \ 83 85 SYMBOL_MARS(ARRAYLITERALT, FLfunc,FREGSAVED,"_d_arrayliteralT", 0, tv) \ 84 86 SYMBOL_MARS(ASSOCARRAYLITERALT, FLfunc,FREGSAVED,"_d_assocarrayliteralT", 0, tv) \ 85 87 SYMBOL_MARS(ASSOCARRAYLITERALTX, FLfunc,FREGSAVED,"_d_assocarrayliteralTX", 0, t) \ 86 88 SYMBOL_MARS(CALLFINALIZER, FLfunc,FREGSAVED,"_d_callfinalizer", 0, t) \ trunk/src/cast.c
r562 r767 1922 1922 1923 1923 int arrayTypeCompatible(Loc loc, Type *t1, Type *t2) 1924 1924 { 1925 1925 t1 = t1->toBasetype(); 1926 1926 t2 = t2->toBasetype(); 1927 1927 1928 1928 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && 1929 1929 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer)) 1930 1930 { 1931 1931 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst && 1932 1932 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst && 1933 1933 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid)) 1934 1934 { 1935 1935 error(loc, "array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars()); 1936 1936 } 1937 1937 return 1; 1938 1938 } 1939 1939 return 0; 1940 1940 } 1941 1941 1942 /*********************************** 1943 * See if both types are arrays that can be compared 1944 * for equality without any casting. Return !=0 if so. 1945 * This is to enable comparing things like an immutable 1946 * array with a mutable one. 1947 */ 1948 int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2) 1949 { 1950 t1 = t1->toBasetype(); 1951 t2 = t2->toBasetype(); 1952 1953 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) && 1954 t2->ty == t1->ty) 1955 { 1956 if (t1->nextOf()->implicitConvTo(t2->nextOf()) >= MATCHconst || 1957 t2->nextOf()->implicitConvTo(t1->nextOf()) >= MATCHconst) 1958 return 1; 1959 } 1960 return 0; 1961 } 1962 1963 1942 1964 /******************************************************************/ 1943 1965 1944 1966 /* Determine the integral ranges of an expression. 1945 1967 * This is used to determine if implicit narrowing conversions will 1946 1968 * be allowed. 1947 1969 */ 1948 1970 1949 1971 uinteger_t getMask(uinteger_t v) 1950 1972 { 1951 1973 uinteger_t u = 0; 1952 1974 if (v >= 0x80) 1953 1975 u = 0xFF; 1954 1976 while (u < v) 1955 1977 u = (u << 1) | 1; 1956 1978 return u; 1957 1979 } 1958 1980 1959 1981 IntRange Expression::getIntRange() 1960 1982 { 1961 1983 IntRange ir; trunk/src/e2ir.c
r738 r767 566 566 return sd; 567 567 } 568 568 return NULL; 569 569 } 570 570 571 571 /******************************************* 572 572 * Set an array pointed to by eptr to evalue: 573 573 * eptr[0..edim] = evalue; 574 574 * Input: 575 575 * eptr where to write the data to 576 576 * evalue value to write 577 577 * edim number of times to write evalue to eptr[] 578 578 * tb type of evalue 579 579 */ 580 580 581 581 elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue, IRState *irs, int op) 582 582 { int r; 583 583 elem *e; 584 584 int sz = tb->size(); 585 585 586 if (tb->ty == Tfloat80 || tb->ty == Timaginary80) 587 r = RTLSYM_MEMSET80; 588 else if (tb->ty == Tcomplex80) 589 r = RTLSYM_MEMSET160; 590 else if (tb->ty == Tcomplex64) 591 r = RTLSYM_MEMSET128; 592 else 593 { 594 switch (sz) 595 { 596 case 1: r = RTLSYM_MEMSET8; break; 597 case 2: r = RTLSYM_MEMSET16; break; 598 case 4: r = RTLSYM_MEMSET32; break; 599 case 8: r = RTLSYM_MEMSET64; break; 600 case 16: r = RTLSYM_MEMSET128; break; 601 default: r = RTLSYM_MEMSETN; break; 602 } 603 604 /* Determine if we need to do postblit 605 */ 606 if (op != TOKblit) 607 { 608 StructDeclaration *sd = needsPostblit(tb); 609 if (sd) 610 { /* Need to do postblit. 611 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); 612 */ 613 r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN; 586 switch (tb->ty) 587 { 588 case Tfloat80: 589 case Timaginary80: 590 r = RTLSYM_MEMSET80; 591 break; 592 case Tcomplex80: 593 r = RTLSYM_MEMSET160; 594 break; 595 case Tcomplex64: 596 r = RTLSYM_MEMSET128; 597 break; 598 case Tfloat32: 599 case Timaginary32: 600 if (I32) 601 goto Ldefault; // legacy binary compatibility 602 r = RTLSYM_MEMSETFLOAT; 603 break; 604 case Tfloat64: 605 case Timaginary64: 606 if (I32) 607 goto Ldefault; // legacy binary compatibility 608 r = RTLSYM_MEMSETDOUBLE; 609 break; 610 611 default: 612 Ldefault: 613 switch (sz) 614 { 615 case 1: r = RTLSYM_MEMSET8; break; 616 case 2: r = RTLSYM_MEMSET16; break; 617 case 4: r = RTLSYM_MEMSET32; break; 618 case 8: r = RTLSYM_MEMSET64; break; 619 case 16: r = RTLSYM_MEMSET128; break; 620 default: r = RTLSYM_MEMSETN; break; 621 } 622 623 /* Determine if we need to do postblit 624 */ 625 if (op != TOKblit) 626 { 627 StructDeclaration *sd = needsPostblit(tb); 628 if (sd) 629 { /* Need to do postblit. 630 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); 631 */ 632 r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN; 633 evalue = el_una(OPaddr, TYnptr, evalue); 634 Expression *ti = tb->getTypeInfo(NULL); 635 elem *eti = ti->toElem(irs); 636 e = el_params(eti, edim, evalue, eptr, NULL); 637 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); 638 return e; 639 } 640 } 641 642 if (r == RTLSYM_MEMSETN) 643 { 644 // void *_memsetn(void *p, void *value, int dim, int sizelem) 614 645 evalue = el_una(OPaddr, TYnptr, evalue); 615 Expression *ti = tb->getTypeInfo(NULL); 616 elem *eti = ti->toElem(irs); 617 e = el_params(eti, edim, evalue, eptr, NULL); 646 elem *esz = el_long(TYsize_t, sz); 647 e = el_params(esz, edim, evalue, eptr, NULL); 618 648 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); 619 649 return e; 620 650 } 621 } 622 623 if (r == RTLSYM_MEMSETN) 624 { 625 // void *_memsetn(void *p, void *value, int dim, int sizelem) 626 evalue = el_una(OPaddr, TYnptr, evalue); 627 elem *esz = el_long(TYsize_t, sz); 628 e = el_params(esz, edim, evalue, eptr, NULL); 629 e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); 630 return e; 631 } 651 break; 632 652 } 633 653 if (sz > 1 && sz <= 8 && 634 654 evalue->Eoper == OPconst && el_allbits(evalue, 0)) 635 655 { 636 656 r = RTLSYM_MEMSET8; 637 657 edim = el_bin(OPmul, TYsize_t, edim, el_long(TYsize_t, sz)); 638 658 } 639 659 640 660 if (tybasic(evalue->Ety) == TYstruct || tybasic(evalue->Ety) == TYarray) 641 661 { 642 662 evalue = el_una(OPstrpar, TYstruct, evalue); 643 663 evalue->ET = evalue->E1->ET; 644 664 } 645 665 646 666 // Be careful about parameter side effect ordering 647 667 if (r == RTLSYM_MEMSET8) 648 668 { 649 669 e = el_param(edim, evalue); 650 670 e = el_bin(OPmemset,TYnptr,eptr,e); 651 671 } trunk/src/expression.c
r755 r767 8560 8560 TypeSArray *tsa = (TypeSArray *)t1; 8561 8561 8562 8562 #if 0 // Don't do now, because it might be short-circuit evaluated 8563 8563 // Do compile time array bounds checking if possible 8564 8564 e2 = e2->optimize(WANTvalue); 8565 8565 if (e2->op == TOKint64) 8566 8566 { 8567 8567 dinteger_t index = e2->toInteger(); 8568 8568 dinteger_t length = tsa->dim->toInteger(); 8569 8569 if (index < 0 || index >= length) 8570 8570 error("array index [%lld] is outside array bounds [0 .. %lld]", 8571 8571 index, length); 8572 8572 } 8573 8573 #endif 8574 8574 e->type = t1->nextOf(); 8575 8575 break; 8576 8576 } 8577 8577 8578 8578 case Taarray: 8579 8579 { TypeAArray *taa = (TypeAArray *)t1; 8580 /* We can skip the implicit conversion if they differ only by 8581 * constness (Bugzilla 2684, see also bug 2954b) 8582 */ 8580 8583 if (!arrayTypeCompatible(e2->loc, e2->type, taa->index)) 8581 8584 { 8582 8585 e2 = e2->implicitCastTo(sc, taa->index); // type checking 8583 8586 } 8584 8587 type = taa->next; 8585 8588 break; 8586 8589 } 8587 8590 8588 8591 case Ttuple: 8589 8592 { 8590 8593 e2 = e2->implicitCastTo(sc, Type::tsize_t); 8591 8594 e2 = e2->optimize(WANTvalue | WANTinterpret); 8592 8595 uinteger_t index = e2->toUInteger(); 8593 8596 size_t length; 8594 8597 TupleExp *te; 8595 8598 TypeTuple *tup; 8596 8599 8597 8600 if (e1->op == TOKtuple) 8598 8601 { te = (TupleExp *)e1; 8599 8602 length = te->exps->dim; trunk/src/imphint.c
r484 r767 1 1 2 2 3 3 // Compiler implementation of the D programming language 4 4 // Copyright (c) 2010 by Digital Mars 5 5 // All Rights Reserved 6 6 // written by Walter Bright 7 7 // http://www.digitalmars.com 8 8 // License for redistribution is by either the Artistic License 9 9 // in artistic.txt, or the GNU General Public License in gnu.txt. 10 10 // See the included readme.txt for details. 11 11 12 12 #include <stdio.h> 13 13 #include <stdlib.h> 14 14 #include <ctype.h> 15 15 #include <assert.h> 16 16 #include <string.h> 17 17 18 #include "mars.h" 19 18 20 /****************************************** 19 21 * Looks for undefined identifier s to see 20 22 * if it might be undefined because an import 21 23 * was not specified. 22 24 * Not meant to be a comprehensive list of names in each module, 23 25 * just the most common ones. 24 26 */ 25 27 26 28 const char *importHint(const char *s) 27 29 { 28 30 #if DMDV1 29 31 static const char *modules[] = 30 32 { "std.c.stdio", 31 33 "std.stdio", 32 34 "std.math", 35 "std.c.stdarg", 33 36 }; 34 37 static const char *names[] = 35 38 { 36 39 "printf", NULL, 37 40 "writefln", NULL, 38 41 "sin", "cos", "sqrt", "fabs", NULL, 42 "__va_argsave_t", NULL, 39 43 }; 40 44 #else 41 45 static const char *modules[] = 42 46 { "core.stdc.stdio", 43 47 "std.stdio", 44 48 "std.math", 49 "std.c.stdarg", 45 50 }; 46 51 static const char *names[] = 47 52 { 48 53 "printf", NULL, 49 54 "writeln", NULL, 50 55 "sin", "cos", "sqrt", "fabs", NULL, 56 "__va_argsave_t", NULL, 51 57 }; 52 58 #endif 53 59 int m = 0; 54 60 for (int n = 0; n < sizeof(names)/sizeof(names[0]); n++) 55 61 { 56 62 const char *p = names[n]; 57 63 if (p == NULL) 58 64 { m++; 59 65 continue; 60 66 } 61 67 assert(m < sizeof(modules)/sizeof(modules[0])); 62 68 if (strcmp(s, p) == 0) 63 69 return modules[m]; 64 70 } 65 71 return NULL; // didn't find it 66 72 } 67 73 68 74 #if UNITTEST 69 75 70 76 void unittest_importHint() trunk/src/mtype.c
r755 r767 5672 5672 if (!scx) 5673 5673 { error(loc, "forward reference to '%s'", t->toChars()); 5674 5674 return; 5675 5675 } 5676 5676 if (scx->scopesym == scopesym) 5677 5677 { 5678 5678 t = t->semantic(loc, scx); 5679 5679 break; 5680 5680 } 5681 5681 } 5682 5682 } 5683 5683 } 5684 5684 } 5685 5685 if (t->ty == Ttuple) 5686 5686 *pt = t; 5687 5687 else 5688 5688 *pt = t->merge(); 5689 5689 } 5690 5690 if (!s) 5691 5691 { 5692 error(loc, "identifier '%s' is not defined", toChars()); 5692 const char *p = toChars(); 5693 const char *n = importHint(p); 5694 if (n) 5695 error(loc, "'%s' is not defined, perhaps you need to import %s; ?", p, n); 5696 else 5697 { 5698 Identifier *id = new Identifier(p, TOKidentifier); 5699 s = sc->search_correct(id); 5700 if (s) 5701 error(loc, "undefined identifier %s, did you mean %s %s?", p, s->kind(), s->toChars()); 5702 else 5703 error(loc, "undefined identifier %s", p); 5704 } 5693 5705 } 5694 5706 } 5695 5707 5696 5708 /***************************** TypeIdentifier *****************************/ 5697 5709 5698 5710 TypeIdentifier::TypeIdentifier(Loc loc, Identifier *ident) 5699 5711 : TypeQualified(Tident, loc) 5700 5712 { 5701 5713 this->ident = ident; 5702 5714 } 5703 5715 5704 5716 5705 5717 Type *TypeIdentifier::syntaxCopy() 5706 5718 { 5707 5719 TypeIdentifier *t; 5708 5720 5709 5721 t = new TypeIdentifier(loc, ident); 5710 5722 t->syntaxCopyHelper(this); 5711 5723 t->mod = mod; 5712 5724 return t; trunk/src/mtype.h
r734 r767 892 892 Parameter *syntaxCopy(); 893 893 Type *isLazyArray(); 894 894 void toDecoBuffer(OutBuffer *buf); 895 895 static Parameters *arraySyntaxCopy(Parameters *args); 896 896 static char *argsTypesToChars(Parameters *args, int varargs); 897 897 static void argsCppMangle(OutBuffer *buf, CppMangleState *cms, Parameters *arguments, int varargs); 898 898 static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Parameters *arguments, int varargs); 899 899 static void argsToDecoBuffer(OutBuffer *buf, Parameters *arguments); 900 900 static int isTPL(Parameters *arguments); 901 901 static size_t dim(Parameters *arguments); 902 902 static Parameter *getNth(Parameters *arguments, size_t nth, size_t *pn = NULL); 903 903 }; 904 904 905 905 extern int PTRSIZE; 906 906 extern int REALSIZE; 907 907 extern int REALPAD; 908 908 extern int Tsize_t; 909 909 extern int Tptrdiff_t; 910 910 911 911 int arrayTypeCompatible(Loc loc, Type *t1, Type *t2); 912 int arrayTypeCompatibleWithoutCasting(Loc loc, Type *t1, Type *t2); 912 913 void MODtoBuffer(OutBuffer *buf, unsigned char mod); 913 914 int MODimplicitConv(unsigned char modfrom, unsigned char modto); 914 915 int MODmerge(unsigned char mod1, unsigned char mod2); 915 916 916 917 #endif /* DMD_MTYPE_H */ trunk/src/toir.c
r728 r767 1 1 2 2 // Compiler implementation of the D programming language 3 // Copyright (c) 1999-20 09by Digital Mars3 // Copyright (c) 1999-2010 by Digital Mars 4 4 // All Rights Reserved 5 5 // written by Walter Bright 6 6 // http://www.digitalmars.com 7 7 // License for redistribution is by either the Artistic License 8 8 // in artistic.txt, or the GNU General Public License in gnu.txt. 9 9 // See the included readme.txt for details. 10 10 11 11 /* Code to help convert to the intermediate representation 12 12 * of the compiler back end. 13 13 */ 14 14 15 15 #include <stdio.h> 16 16 #include <string.h> 17 17 #include <time.h> 18 18 #include <complex.h> 19 19 20 20 #include "lexer.h" 21 21 #include "expression.h" 22 22 #include "mtype.h" 23 23 #include "dsymbol.h" … … 194 194 * function must be a member function of that aggregate. 195 195 */ 196 196 ClassDeclaration *cd; 197 197 StructDeclaration *sd; 198 198 AggregateDeclaration *ad = s->isAggregateDeclaration(); 199 199 if (!ad) 200 200 goto Lnoframe; 201 201 cd = s->isClassDeclaration(); 202 202 if (cd && fd->isClassDeclaration() && 203 203 fd->isClassDeclaration()->isBaseOf(cd, NULL)) 204 204 break; 205 205 sd = s->isStructDeclaration(); 206 206 if (fd == sd) 207 207 break; 208 208 if (!ad->isNested() || !ad->vthis) 209 209 { 210 210 Lnoframe: 211 211 irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars()); 212 212 return el_long(TYnptr, 0); // error recovery 213 213 } 214 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TY int, ad->vthis->offset));214 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, ad->vthis->offset)); 215 215 ethis = el_una(OPind, TYnptr, ethis); 216 216 if (fdparent == s->toParent2()) 217 217 break; 218 218 if (fd == s->toParent2()) 219 219 { 220 220 /* Remember that frames for functions that have no 221 221 * nested references are skipped in the linked list 222 222 * of frames. 223 223 */ 224 224 #if DMDV2 225 225 if (s->toParent2()->isFuncDeclaration()->closureVars.dim) 226 226 #else 227 227 if (s->toParent2()->isFuncDeclaration()->nestedFrameRef) 228 228 #endif 229 229 ethis = el_una(OPind, TYnptr, ethis); 230 230 break; 231 231 } 232 232 if (s->toParent2()->isFuncDeclaration()) 233 233 { 234 234 /* Remember that frames for functions that have no … … 306 306 } 307 307 } 308 308 else if (thisfd->vthis && 309 309 (cdp == thisfd->toParent2() || 310 310 (cdp->isClassDeclaration() && 311 311 cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset) 312 312 ) 313 313 ) 314 314 ) 315 315 { /* Class we're new'ing is at the same level as thisfd 316 316 */ 317 317 assert(offset == 0); // BUG: should handle this case 318 318 ethis = el_var(irs->sthis); 319 319 } 320 320 else 321 321 { 322 322 ethis = getEthis(loc, irs, ad->toParent2()); 323 323 ethis = el_una(OPaddr, TYnptr, ethis); 324 324 } 325 325 326 ey = el_bin(OPadd, TYnptr, ey, el_long(TY int, ad->vthis->offset));326 ey = el_bin(OPadd, TYnptr, ey, el_long(TYsize_t, ad->vthis->offset)); 327 327 ey = el_una(OPind, TYnptr, ey); 328 328 ey = el_bin(OPeq, TYnptr, ey, ethis); 329 329 return ey; 330 330 } 331 331 #endif 332 332 333 333 /******************************************* 334 334 * Convert intrinsic function to operator. 335 335 * Returns that operator, -1 if not an intrinsic function. 336 336 */ 337 337 338 338 int intrinsic_op(char *name) 339 339 { 340 340 //printf("intrinsic_op(%s)\n", name); 341 341 static const char *namearray[] = 342 342 { 343 343 #if DMDV1 344 344 "4math3cosFeZe", 345 345 "4math3sinFeZe", 346 346 "4math4fabsFeZe", … … 395 395 "9intrinsic5bswapFNaNbkZk", 396 396 "9intrinsic5outplFNbkkZk", 397 397 "9intrinsic5outpwFNbktZt", 398 398 #endif 399 399 }; 400 400 static const char *namearray64[] = 401 401 { 402 402 #if DMDV1 403 403 "4math3cosFeZe", 404 404 "4math3sinFeZe", 405 405 "4math4fabsFeZe", 406 406 "4math4rintFeZe", 407 407 "4math4sqrtFdZd", 408 408 "4math4sqrtFeZe", 409 409 "4math4sqrtFfZf", 410 410 "4math4yl2xFeeZe", 411 411 "4math5ldexpFeiZe", 412 412 "4math6rndtolFeZl", 413 413 "4math6yl2xp1FeeZe", 414 414 415 "9intrinsic2btFP kkZi",415 "9intrinsic2btFPmmZi", 416 416 "9intrinsic3bsfFkZi", 417 417 "9intrinsic3bsrFkZi", 418 418 "9intrinsic3btcFPmmZi", 419 419 "9intrinsic3btrFPmmZi", 420 420 "9intrinsic3btsFPmmZi", 421 421 "9intrinsic3inpFkZh", 422 422 "9intrinsic4inplFkZk", 423 423 "9intrinsic4inpwFkZt", 424 424 "9intrinsic4outpFkhZh", 425 425 "9intrinsic5bswapFkZk", 426 426 "9intrinsic5outplFkkZk", 427 427 "9intrinsic5outpwFktZt", 428 428 #elif DMDV2 429 429 /* The names are mangled differently because of the pure and 430 430 * nothrow attributes. 431 431 */ 432 432 "4math3cosFNaNbNfeZe", 433 433 "4math3sinFNaNbNfeZe", 434 434 "4math4fabsFNaNbNfeZe", 435 435 "4math4rintFNaNbNfeZe", … … 527 527 * t1 Type of the array 528 528 * Output: 529 529 * e is rewritten to avoid side effects 530 530 * Returns: 531 531 * expression that initializes 'length' 532 532 */ 533 533 534 534 elem *resolveLengthVar(VarDeclaration *lengthVar, elem **pe, Type *t1) 535 535 { 536 536 //printf("resolveLengthVar()\n"); 537 537 elem *einit = NULL; 538 538 539 539 if (lengthVar && !(lengthVar->storage_class & STCconst)) 540 540 { elem *elength; 541 541 Symbol *slength; 542 542 543 543 if (t1->ty == Tsarray) 544 544 { TypeSArray *tsa = (TypeSArray *)t1; 545 545 dinteger_t length = tsa->dim->toInteger(); 546 546 547 elength = el_long(TY uint, length);547 elength = el_long(TYsize_t, length); 548 548 goto L3; 549 549 } 550 550 else if (t1->ty == Tarray) 551 551 { 552 552 elength = *pe; 553 553 *pe = el_same(&elength); 554 elength = el_una( OP64_32, TYuint, elength);554 elength = el_una(I64 ? OP128_64 : OP64_32, TYsize_t, elength); 555 555 556 556 L3: 557 557 slength = lengthVar->toSymbol(); 558 558 //symbol_add(slength); 559 559 560 einit = el_bin(OPeq, TY uint, el_var(slength), elength);560 einit = el_bin(OPeq, TYsize_t, el_var(slength), elength); 561 561 } 562 562 } 563 563 return einit; 564 564 } 565 565 566 566 /************************************* 567 567 * Closures are implemented by taking the local variables that 568 568 * need to survive the scope of the function, and copying them 569 569 * into a gc allocated chuck of memory. That chunk, called the 570 570 * closure here, is inserted into the linked list of stack 571 571 * frames instead of the usual stack frame. 572 572 * 573 573 * buildClosure() inserts code just after the function prolog 574 574 * is complete. It allocates memory for the closure, allocates 575 575 * a local variable (sclosure) to point to it, inserts into it 576 576 * the link to the enclosing frame, and copies into it the parameters 577 577 * that are referred to in nested functions. 578 578 * In VarExp::toElem and SymOffExp::toElem, when referring to a 579 579 * variable that is in a closure, takes the offset from sclosure rather 580 580 * than from the frame pointer. … … 657 657 memsize = v->type->size(); 658 658 memalignsize = v->type->alignsize(); 659 659 xalign = v->type->memalign(global.structalign); 660 660 } 661 661 AggregateDeclaration::alignmember(xalign, memalignsize, &offset); 662 662 v->offset = offset; 663 663 offset += memsize; 664 664 665 665 /* Can't do nrvo if the variable is put in a closure, since 666 666 * what the shidden points to may no longer exist. 667 667 */ 668 668 if (nrvo_can && nrvo_var == v) 669 669 { 670 670 nrvo_can = 0; 671 671 } 672 672 } 673 673 // offset is now the size of the closure 674 674 675 675 // Allocate memory for the closure 676 676 elem *e; 677 e = el_long(TY int, offset);677 e = el_long(TYsize_t, offset); 678 678 e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e); 679 679 680 680 // Assign block of memory to sclosure 681 681 // sclosure = allocmemory(sz); 682 682 e = el_bin(OPeq, TYvoid, el_var(sclosure), e); 683 683 684 684 // Set the first element to sthis 685 685 // *(sclosure + 0) = sthis; 686 686 elem *ethis; 687 687 if (irs->sthis) 688 688 ethis = el_var(irs->sthis); 689 689 else 690 690 ethis = el_long(TYnptr, 0); 691 691 elem *ex = el_una(OPind, TYnptr, el_var(sclosure)); 692 692 ex = el_bin(OPeq, TYnptr, ex, ethis); 693 693 e = el_combine(e, ex); 694 694 695 695 // Copy function parameters into closure 696 696 for (int i = 0; i < closureVars.dim; i++) 697 697 { VarDeclaration *v = (VarDeclaration *)closureVars.data[i]; 698 698 699 699 if (!v->isParameter()) 700 700 continue; 701 701 tym_t tym = v->type->totym(); 702 702 if ( 703 703 #if !SARRAYVALUE 704 704 v->type->toBasetype()->ty == Tsarray || 705 705 #endif 706 706 v->isOut() || v->isRef()) 707 707 tym = TYnptr; // reference parameters are just pointers 708 708 #if DMDV2 709 709 else if (v->storage_class & STClazy) 710 710 tym = TYdelegate; 711 711 #endif 712 ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TY int, v->offset));712 ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYsize_t, v->offset)); 713 713 ex = el_una(OPind, tym, ex); 714 714 if (tybasic(ex->Ety) == TYstruct || tybasic(ex->Ety) == TYarray) 715 715 { 716 716 ::type *t = v->type->toCtype(); 717 717 ex->ET = t; 718 718 ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol())); 719 719 ex->ET = t; 720 720 } 721 721 else 722 722 ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol())); 723 723 724 724 e = el_combine(e, ex); 725 725 } 726 726 727 727 block_appendexp(irs->blx->curblock, e); 728 728 } 729 729 } 730 730 731 731 #endif 732 732
