Mercurial > projects > ddmd
annotate dmd/CmpExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | 6caaf0256da1 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.CmpExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
5 import dmd.Identifier; | |
6 import dmd.backend.elem; | |
7 import dmd.InterState; | |
8 import dmd.Loc; | |
9 import dmd.TOK; | |
10 import dmd.Scope; | |
11 import dmd.IRState; | |
0 | 12 import dmd.Type; |
13 import dmd.Id; | |
14 import dmd.TY; | |
15 import dmd.ErrorExp; | |
16 import dmd.IntegerExp; | |
17 import dmd.MATCH; | |
18 import dmd.BinExp; | |
19 import dmd.WANT; | |
20 import dmd.GlobalExpressions; | |
21 | |
22 import dmd.expression.Util; | |
23 import dmd.codegen.Util; | |
24 import dmd.expression.Cmp; | |
25 | |
26 import dmd.backend.Util; | |
27 import dmd.backend.RTLSYM; | |
28 import dmd.backend.TYM; | |
29 import dmd.backend.OPER; | |
72 | 30 import dmd.backend.rel; |
31 | |
0 | 32 class CmpExp : BinExp |
33 { | |
34 this(TOK op, Loc loc, Expression e1, Expression e2) | |
72 | 35 { |
178 | 36 register(); |
37 | |
0 | 38 super(loc, op, CmpExp.sizeof, e1, e2); |
39 } | |
40 | |
72 | 41 override Expression semantic(Scope sc) |
0 | 42 { |
43 Expression e; | |
44 | |
45 version (LOGSEMANTIC) { | |
46 printf("CmpExp.semantic('%s')\n", toChars()); | |
47 } | |
48 if (type) | |
49 return this; | |
50 | |
51 BinExp.semanticp(sc); | |
52 | |
79 | 53 Type t1 = e1.type.toBasetype(); |
54 Type t2 = e2.type.toBasetype(); | |
55 if (t1.ty == Tclass && e2.op == TOKnull || | |
56 t2.ty == Tclass && e1.op == TOKnull) | |
0 | 57 { |
58 error("do not use null when comparing class types"); | |
59 } | |
60 | |
61 e = op_overload(sc); | |
62 if (e) | |
63 { | |
64 if (!e.type.isscalar() && e.type.equals(e1.type)) | |
65 { | |
66 error("recursive opCmp expansion"); | |
67 e = new ErrorExp(); | |
68 } | |
69 else | |
70 { | |
71 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type.tint32)); | |
72 e = e.semantic(sc); | |
73 } | |
74 return e; | |
75 } | |
76 | |
79 | 77 // Disallow comparing T[]==T and T==T[] |
78 if (e1.op == TOKslice && t1.ty == Tarray && e2.implicitConvTo(t1.nextOf()) || | |
79 e2.op == TOKslice && t2.ty == Tarray && e1.implicitConvTo(t2.nextOf())) | |
80 { | |
81 incompatibleTypes(); | |
82 return new ErrorExp(); | |
83 } | |
84 | |
0 | 85 typeCombine(sc); |
86 type = Type.tboolean; | |
87 | |
88 // Special handling for array comparisons | |
89 t1 = e1.type.toBasetype(); | |
90 t2 = e2.type.toBasetype(); | |
91 if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && | |
92 (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer)) | |
93 { | |
94 if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCHconst && | |
95 t2.nextOf().implicitConvTo(t1.nextOf()) < MATCHconst && | |
96 (t1.nextOf().ty != Tvoid && t2.nextOf().ty != Tvoid)) | |
97 error("array comparison type mismatch, %s vs %s", t1.nextOf().toChars(), t2.nextOf().toChars()); | |
98 e = this; | |
99 } | |
100 else if (t1.ty == Tstruct || t2.ty == Tstruct || | |
101 (t1.ty == Tclass && t2.ty == Tclass)) | |
102 { | |
103 if (t2.ty == Tstruct) | |
104 error("need member function opCmp() for %s %s to compare", t2.toDsymbol(sc).kind(), t2.toChars()); | |
105 else | |
106 error("need member function opCmp() for %s %s to compare", t1.toDsymbol(sc).kind(), t1.toChars()); | |
107 e = this; | |
108 } | |
109 /// static if (true) { | |
110 else if (t1.iscomplex() || t2.iscomplex()) | |
111 { | |
112 error("compare not defined for complex operands"); | |
113 e = new ErrorExp(); | |
114 } | |
115 /// } | |
116 else | |
117 { | |
118 e1.rvalue(); | |
119 e2.rvalue(); | |
120 e = this; | |
121 } | |
122 | |
123 //printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars()); | |
124 return e; | |
125 } | |
126 | |
72 | 127 override Expression optimize(int result) |
0 | 128 { |
129 Expression e; | |
130 | |
131 //printf("CmpExp::optimize() %s\n", toChars()); | |
132 e1 = e1.optimize(WANTvalue | (result & WANTinterpret)); | |
133 e2 = e2.optimize(WANTvalue | (result & WANTinterpret)); | |
134 | |
135 Expression e1 = fromConstInitializer(result, this.e1); | |
136 Expression e2 = fromConstInitializer(result, this.e2); | |
137 | |
138 e = Cmp(op, type, e1, e2); | |
139 if (e is EXP_CANT_INTERPRET) | |
140 e = this; | |
141 return e; | |
142 } | |
143 | |
72 | 144 override Expression interpret(InterState istate) |
0 | 145 { |
115
6caaf0256da1
+ interpretation of (non-assign) binary expressions
Trass3r
parents:
114
diff
changeset
|
146 return interpretCommon2(istate, &Cmp); |
0 | 147 } |
148 | |
72 | 149 override int isBit() |
0 | 150 { |
151 assert(false); | |
152 } | |
153 | |
72 | 154 override bool isCommutative() |
0 | 155 { |
156 return true; | |
157 } | |
158 | |
72 | 159 override Identifier opId() |
0 | 160 { |
161 return Id.cmp; | |
162 } | |
163 | |
72 | 164 override elem* toElem(IRState* irs) |
0 | 165 { |
166 elem *e; | |
167 OPER eop; | |
168 Type t1 = e1.type.toBasetype(); | |
169 Type t2 = e2.type.toBasetype(); | |
170 | |
171 switch (op) | |
172 { | |
173 case TOKlt: eop = OPlt; break; | |
174 case TOKgt: eop = OPgt; break; | |
175 case TOKle: eop = OPle; break; | |
176 case TOKge: eop = OPge; break; | |
177 case TOKequal: eop = OPeqeq; break; | |
178 case TOKnotequal: eop = OPne; break; | |
179 | |
180 // NCEG floating point compares | |
181 case TOKunord: eop = OPunord; break; | |
182 case TOKlg: eop = OPlg; break; | |
183 case TOKleg: eop = OPleg; break; | |
184 case TOKule: eop = OPule; break; | |
185 case TOKul: eop = OPul; break; | |
186 case TOKuge: eop = OPuge; break; | |
187 case TOKug: eop = OPug; break; | |
188 case TOKue: eop = OPue; break; | |
189 default: | |
190 dump(0); | |
191 assert(0); | |
192 } | |
193 if (!t1.isfloating()) | |
194 { | |
195 // Convert from floating point compare to equivalent | |
196 // integral compare | |
197 eop = cast(OPER)rel_integral(eop); | |
198 } | |
199 if (cast(int)eop > 1 && t1.ty == Tclass && t2.ty == Tclass) | |
200 { | |
201 static if (true) { | |
202 assert(0); | |
203 } else { | |
204 elem *ec1; | |
205 elem *ec2; | |
206 | |
207 ec1 = e1.toElem(irs); | |
208 ec2 = e2.toElem(irs); | |
209 e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2)); | |
210 e = el_bin(eop, TYint, e, el_long(TYint, 0)); | |
211 } | |
212 } | |
213 else if (cast(int)eop > 1 && | |
214 (t1.ty == Tarray || t1.ty == Tsarray) && | |
215 (t2.ty == Tarray || t2.ty == Tsarray)) | |
216 { | |
217 elem* ea1; | |
218 elem* ea2; | |
219 elem* ep; | |
220 Type telement = t1.nextOf().toBasetype(); | |
221 int rtlfunc; | |
222 | |
223 ea1 = e1.toElem(irs); | |
224 ea1 = array_toDarray(t1, ea1); | |
225 ea2 = e2.toElem(irs); | |
226 ea2 = array_toDarray(t2, ea2); | |
227 | |
228 version (DMDV2) { | |
229 ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), | |
230 ea2, ea1, null); | |
231 rtlfunc = RTLSYM_ARRAYCMP2; | |
232 } else { | |
233 ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); | |
234 rtlfunc = RTLSYM_ARRAYCMP; | |
235 } | |
236 e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); | |
237 e = el_bin(eop, TYint, e, el_long(TYint, 0)); | |
238 el_setLoc(e,loc); | |
239 } | |
240 else | |
241 { | |
242 if (cast(int)eop <= 1) | |
243 { | |
244 /* The result is determinate, create: | |
245 * (e1 , e2) , eop | |
246 */ | |
247 e = toElemBin(irs,OPcomma); | |
248 e = el_bin(OPcomma,e.Ety,e,el_long(e.Ety,cast(int)eop)); | |
249 } | |
250 else | |
251 e = toElemBin(irs,eop); | |
252 } | |
253 return e; | |
254 } | |
255 } | |
256 |