Mercurial > projects > ddmd
comparison dmd/AddrExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 2e2a5c3f943a |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.AddrExp; | |
2 | |
3 import dmd.Expression; | |
4 import dmd.UnaExp; | |
5 import dmd.MATCH; | |
6 import dmd.Type; | |
7 import dmd.Loc; | |
8 import dmd.Scope; | |
9 import dmd.IRState; | |
10 import dmd.ErrorExp; | |
11 import dmd.DotVarExp; | |
12 import dmd.FuncDeclaration; | |
13 import dmd.DelegateExp; | |
14 import dmd.VarExp; | |
15 import dmd.VarDeclaration; | |
16 import dmd.ThisExp; | |
17 import dmd.TOK; | |
18 import dmd.WANT; | |
19 import dmd.CommaExp; | |
20 import dmd.STC; | |
21 import dmd.PtrExp; | |
22 import dmd.SymOffExp; | |
23 import dmd.IndexExp; | |
24 import dmd.OverExp; | |
25 import dmd.Dsymbol; | |
26 import dmd.ScopeDsymbol; | |
27 import dmd.TY; | |
28 import dmd.TypeSArray; | |
29 | |
30 import dmd.backend.elem; | |
31 import dmd.backend.Util; | |
32 import dmd.codegen.Util; | |
33 | |
34 class AddrExp : UnaExp | |
35 { | |
36 this(Loc loc, Expression e) | |
37 { | |
38 super(loc, TOK.TOKaddress, AddrExp.sizeof, e); | |
39 } | |
40 | |
41 Expression semantic(Scope sc) | |
42 { | |
43 version (LOGSEMANTIC) { | |
44 printf("AddrExp.semantic('%s')\n", toChars()); | |
45 } | |
46 if (!type) | |
47 { | |
48 UnaExp.semantic(sc); | |
49 e1 = e1.toLvalue(sc, null); | |
50 if (!e1.type) | |
51 { | |
52 error("cannot take address of %s", e1.toChars()); | |
53 return new ErrorExp(); | |
54 } | |
55 if (!e1.type.deco) | |
56 { | |
57 /* No deco means semantic() was not run on the type. | |
58 * We have to run semantic() on the symbol to get the right type: | |
59 * auto x = &bar; | |
60 * pure: int bar() { return 1;} | |
61 * otherwise the 'pure' is missing from the type assigned to x. | |
62 */ | |
63 | |
64 error("forward reference to %s", e1.toChars()); | |
65 return new ErrorExp(); | |
66 } | |
67 | |
68 //printf("test3 deco = %p\n", e1.type.deco); | |
69 type = e1.type.pointerTo(); | |
70 | |
71 // See if this should really be a delegate | |
72 if (e1.op == TOKdotvar) | |
73 { | |
74 DotVarExp dve = cast(DotVarExp)e1; | |
75 FuncDeclaration f = dve.var.isFuncDeclaration(); | |
76 | |
77 if (f) | |
78 { | |
79 if (!dve.hasOverloads) | |
80 f.tookAddressOf++; | |
81 Expression e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads); | |
82 e = e.semantic(sc); | |
83 return e; | |
84 } | |
85 } | |
86 else if (e1.op == TOKvar) | |
87 { | |
88 VarExp ve = cast(VarExp)e1; | |
89 | |
90 VarDeclaration v = ve.var.isVarDeclaration(); | |
91 if (v && !v.canTakeAddressOf()) | |
92 error("cannot take address of %s", e1.toChars()); | |
93 | |
94 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
95 | |
96 if (f) | |
97 { | |
98 if (!ve.hasOverloads || | |
99 /* Because nested functions cannot be overloaded, | |
100 * mark here that we took its address because castTo() | |
101 * may not be called with an exact match. | |
102 */ | |
103 f.toParent2().isFuncDeclaration()) | |
104 f.tookAddressOf++; | |
105 | |
106 if (f.isNested()) | |
107 { | |
108 Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads); | |
109 e = e.semantic(sc); | |
110 return e; | |
111 } | |
112 if (f.needThis() && hasThis(sc)) | |
113 { | |
114 /* Should probably supply 'this' after overload resolution, | |
115 * not before. | |
116 */ | |
117 Expression ethis = new ThisExp(loc); | |
118 Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads); | |
119 e = e.semantic(sc); | |
120 return e; | |
121 } | |
122 } | |
123 } | |
124 return optimize(WANTvalue); | |
125 } | |
126 return this; | |
127 } | |
128 | |
129 elem* toElem(IRState* irs) | |
130 { | |
131 elem* e; | |
132 | |
133 //printf("AddrExp.toElem('%s')\n", toChars()); | |
134 | |
135 e = e1.toElem(irs); | |
136 e = addressElem(e, e1.type); | |
137 L2: | |
138 e.Ety = type.totym(); | |
139 el_setLoc(e,loc); | |
140 return e; | |
141 } | |
142 | |
143 MATCH implicitConvTo(Type t) | |
144 { | |
145 static if (false) { | |
146 printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n", | |
147 toChars(), type.toChars(), t.toChars()); | |
148 } | |
149 MATCH result; | |
150 | |
151 result = type.implicitConvTo(t); | |
152 //printf("\tresult = %d\n", result); | |
153 | |
154 if (result == MATCHnomatch) | |
155 { | |
156 // Look for pointers to functions where the functions are overloaded. | |
157 | |
158 t = t.toBasetype(); | |
159 | |
160 if (e1.op == TOKoverloadset && | |
161 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
162 { | |
163 OverExp eo = cast(OverExp)e1; | |
164 FuncDeclaration f = null; | |
165 for (int i = 0; i < eo.vars.a.dim; i++) | |
166 { | |
167 Dsymbol s = cast(Dsymbol)eo.vars.a.data[i]; | |
168 FuncDeclaration f2 = s.isFuncDeclaration(); | |
169 assert(f2); | |
170 if (f2.overloadExactMatch(t.nextOf())) | |
171 { | |
172 if (f) | |
173 /* Error if match in more than one overload set, | |
174 * even if one is a 'better' match than the other. | |
175 */ | |
176 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
177 else | |
178 f = f2; | |
179 result = MATCHexact; | |
180 } | |
181 } | |
182 } | |
183 | |
184 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
185 t.ty == Tpointer && t.nextOf().ty == Tfunction && | |
186 e1.op == TOKvar) | |
187 { | |
188 /* I don't think this can ever happen - | |
189 * it should have been | |
190 * converted to a SymOffExp. | |
191 */ | |
192 assert(0); | |
193 VarExp ve = cast(VarExp)e1; | |
194 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
195 if (f && f.overloadExactMatch(t.nextOf())) | |
196 result = MATCHexact; | |
197 } | |
198 } | |
199 | |
200 //printf("\tresult = %d\n", result); | |
201 return result; | |
202 } | |
203 | |
204 Expression castTo(Scope sc, Type t) | |
205 { | |
206 Type tb; | |
207 | |
208 static if (false) { | |
209 printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); | |
210 } | |
211 Expression e = this; | |
212 | |
213 tb = t.toBasetype(); | |
214 type = type.toBasetype(); | |
215 if (tb != type) | |
216 { | |
217 // Look for pointers to functions where the functions are overloaded. | |
218 | |
219 if (e1.op == TOKoverloadset && | |
220 (t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction) | |
221 { | |
222 OverExp eo = cast(OverExp)e1; | |
223 FuncDeclaration f = null; | |
224 for (int i = 0; i < eo.vars.a.dim; i++) | |
225 { | |
226 Dsymbol s = cast(Dsymbol)eo.vars.a.data[i]; | |
227 FuncDeclaration f2 = s.isFuncDeclaration(); | |
228 assert(f2); | |
229 if (f2.overloadExactMatch(t.nextOf())) | |
230 { | |
231 if (f) | |
232 /* Error if match in more than one overload set, | |
233 * even if one is a 'better' match than the other. | |
234 */ | |
235 ScopeDsymbol.multiplyDefined(loc, f, f2); | |
236 else | |
237 f = f2; | |
238 } | |
239 } | |
240 if (f) | |
241 { | |
242 f.tookAddressOf++; | |
243 SymOffExp se = new SymOffExp(loc, f, 0, 0); | |
244 se.semantic(sc); | |
245 // Let SymOffExp.castTo() do the heavy lifting | |
246 return se.castTo(sc, t); | |
247 } | |
248 } | |
249 | |
250 | |
251 if (type.ty == Tpointer && type.nextOf().ty == Tfunction && | |
252 tb.ty == Tpointer && tb.nextOf().ty == Tfunction && | |
253 e1.op == TOKvar) | |
254 { | |
255 VarExp ve = cast(VarExp)e1; | |
256 FuncDeclaration f = ve.var.isFuncDeclaration(); | |
257 if (f) | |
258 { | |
259 assert(0); // should be SymOffExp instead | |
260 f = f.overloadExactMatch(tb.nextOf()); | |
261 if (f) | |
262 { | |
263 e = new VarExp(loc, f); | |
264 e.type = f.type; | |
265 e = new AddrExp(loc, e); | |
266 e.type = t; | |
267 return e; | |
268 } | |
269 } | |
270 } | |
271 e = Expression.castTo(sc, t); | |
272 } | |
273 e.type = t; | |
274 return e; | |
275 } | |
276 | |
277 Expression optimize(int result) | |
278 { | |
279 Expression e; | |
280 | |
281 //printf("AddrExp.optimize(result = %d) %s\n", result, toChars()); | |
282 | |
283 /* Rewrite &(a,b) as (a,&b) | |
284 */ | |
285 if (e1.op == TOKcomma) | |
286 { | |
287 CommaExp ce = cast(CommaExp)e1; | |
288 AddrExp ae = new AddrExp(loc, ce.e2); | |
289 ae.type = type; | |
290 e = new CommaExp(ce.loc, ce.e1, ae); | |
291 e.type = type; | |
292 return e.optimize(result); | |
293 } | |
294 | |
295 if (e1.op == TOKvar) | |
296 { | |
297 VarExp ve = cast(VarExp)e1; | |
298 if (ve.var.storage_class & STCmanifest) | |
299 e1 = e1.optimize(result); | |
300 } | |
301 else | |
302 e1 = e1.optimize(result); | |
303 | |
304 // Convert &*ex to ex | |
305 if (e1.op == TOKstar) | |
306 { | |
307 Expression ex; | |
308 | |
309 ex = (cast(PtrExp)e1).e1; | |
310 if (type.equals(ex.type)) | |
311 e = ex; | |
312 else | |
313 { | |
314 e = ex.copy(); | |
315 e.type = type; | |
316 } | |
317 return e; | |
318 } | |
319 if (e1.op == TOKvar) | |
320 { | |
321 VarExp ve = cast(VarExp)e1; | |
322 if (!ve.var.isOut() && !ve.var.isRef() && | |
323 !ve.var.isImportedSymbol()) | |
324 { | |
325 SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads); | |
326 se.type = type; | |
327 return se; | |
328 } | |
329 } | |
330 if (e1.op == TOKindex) | |
331 { | |
332 // Convert &array[n] to &array+n | |
333 IndexExp ae = cast(IndexExp)e1; | |
334 | |
335 if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar) | |
336 { | |
337 long index = ae.e2.toInteger(); | |
338 VarExp ve = cast(VarExp)ae.e1; | |
339 if (ve.type.ty == Tsarray | |
340 && !ve.var.isImportedSymbol()) | |
341 { | |
342 TypeSArray ts = cast(TypeSArray)ve.type; | |
343 long dim = ts.dim.toInteger(); | |
344 if (index < 0 || index >= dim) | |
345 error("array index %jd is out of bounds [0..%jd]", index, dim); | |
346 e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size())); | |
347 e.type = type; | |
348 return e; | |
349 } | |
350 } | |
351 } | |
352 return this; | |
353 } | |
354 } | |
355 |