Mercurial > projects > ddmd
annotate dmd/NewExp.d @ 179:cd48cb899aee
Updated to dmd2.040
author | korDen |
---|---|
date | Sun, 17 Oct 2010 20:56:07 +0400 |
parents | e3afd1303184 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.NewExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
179 | 5 import dmd.GlobalExpressions; |
72 | 6 import dmd.NewDeclaration; |
0 | 7 import dmd.CtorDeclaration; |
72 | 8 import dmd.ClassDeclaration; |
179 | 9 import dmd.InterState; |
72 | 10 import dmd.Type; |
11 import dmd.OutBuffer; | |
174 | 12 import dmd.PREC; |
72 | 13 import dmd.Loc; |
14 import dmd.Scope; | |
15 import dmd.IRState; | |
16 import dmd.InlineDoState; | |
17 import dmd.HdrGenState; | |
18 import dmd.ArrayTypes; | |
0 | 19 import dmd.TOK; |
20 import dmd.TY; | |
21 import dmd.TypeFunction; | |
22 import dmd.TypeClass; | |
23 import dmd.TypeStruct; | |
24 import dmd.StructDeclaration; | |
25 import dmd.FuncDeclaration; | |
26 import dmd.TypeDArray; | |
27 import dmd.Dsymbol; | |
28 import dmd.ThisExp; | |
29 import dmd.DotIdExp; | |
30 import dmd.Id; | |
31 import dmd.WANT; | |
32 import dmd.Global; | |
33 import dmd.IntegerExp; | |
34 import dmd.TypePointer; | |
72 | 35 |
179 | 36 import dmd.interpret.Util; |
37 import dmd.expression.Util; | |
38 | |
0 | 39 import dmd.backend.elem; |
40 import dmd.backend.TYM; | |
41 import dmd.backend.SC; | |
42 import dmd.backend.TYPE; | |
43 import dmd.backend.TYM; | |
44 import dmd.backend.Symbol; | |
45 import dmd.backend.Classsym; | |
46 import dmd.backend.Util; | |
47 import dmd.backend.OPER; | |
48 import dmd.backend.RTLSYM; | |
49 import dmd.codegen.Util; | |
50 | |
72 | 51 import std.string : toStringz; |
52 | |
0 | 53 class NewExp : Expression |
54 { | |
72 | 55 /* thisexp.new(newargs) newtype(arguments) |
56 */ | |
57 Expression thisexp; // if !null, 'this' for class being allocated | |
58 Expressions newargs; // Array of Expression's to call new operator | |
59 Type newtype; | |
60 Expressions arguments; // Array of Expression's | |
61 | |
62 CtorDeclaration member; // constructor function | |
63 NewDeclaration allocator; // allocator function | |
0 | 64 int onstack; // allocate on stack |
65 | |
66 this(Loc loc, Expression thisexp, Expressions newargs, Type newtype, Expressions arguments) | |
67 { | |
178 | 68 register(); |
0 | 69 super(loc, TOK.TOKnew, NewExp.sizeof); |
70 this.thisexp = thisexp; | |
71 this.newargs = newargs; | |
72 this.newtype = newtype; | |
73 this.arguments = arguments; | |
74 } | |
75 | |
72 | 76 override Expression syntaxCopy() |
0 | 77 { |
72 | 78 return new NewExp(loc, |
79 thisexp ? thisexp.syntaxCopy() : null, | |
80 arraySyntaxCopy(newargs), | |
53 | 81 newtype.syntaxCopy(), arraySyntaxCopy(arguments)); |
0 | 82 } |
83 | |
72 | 84 override Expression semantic(Scope sc) |
0 | 85 { |
86 int i; | |
87 Type tb; | |
88 ClassDeclaration cdthis = null; | |
89 | |
90 version (LOGSEMANTIC) { | |
91 printf("NewExp.semantic() %s\n", toChars()); | |
92 if (thisexp) | |
93 printf("\tthisexp = %s\n", thisexp.toChars()); | |
94 printf("\tnewtype: %s\n", newtype.toChars()); | |
95 } | |
96 if (type) // if semantic() already run | |
97 return this; | |
98 | |
99 Lagain: | |
100 if (thisexp) | |
174 | 101 { |
0 | 102 thisexp = thisexp.semantic(sc); |
103 cdthis = thisexp.type.isClassHandle(); | |
104 if (cdthis) | |
105 { | |
106 sc = sc.push(cdthis); | |
107 type = newtype.semantic(loc, sc); | |
108 sc = sc.pop(); | |
109 } | |
110 else | |
111 { | |
112 error("'this' for nested class must be a class type, not %s", thisexp.type.toChars()); | |
113 type = newtype.semantic(loc, sc); | |
114 } | |
115 } | |
116 else | |
117 type = newtype.semantic(loc, sc); | |
118 newtype = type; // in case type gets cast to something else | |
119 tb = type.toBasetype(); | |
120 //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco); | |
121 | |
122 arrayExpressionSemantic(newargs, sc); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
123 preFunctionParameters(loc, sc, newargs); |
0 | 124 arrayExpressionSemantic(arguments, sc); |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
125 preFunctionParameters(loc, sc, arguments); |
0 | 126 |
127 if (thisexp && tb.ty != Tclass) | |
128 error("e.new is only for allocating nested classes, not %s", tb.toChars()); | |
129 | |
130 if (tb.ty == Tclass) | |
174 | 131 { |
0 | 132 TypeFunction tf; |
133 | |
134 TypeClass tc = cast(TypeClass)tb; | |
135 ClassDeclaration cd = tc.sym.isClassDeclaration(); | |
136 if (cd.isInterfaceDeclaration()) | |
137 error("cannot create instance of interface %s", cd.toChars()); | |
138 else if (cd.isAbstract()) | |
174 | 139 { |
0 | 140 error("cannot create instance of abstract class %s", cd.toChars()); |
141 for (int j = 0; j < cd.vtbl.dim; j++) | |
174 | 142 { |
0 | 143 FuncDeclaration fd = (cast(Dsymbol)cd.vtbl.data[j]).isFuncDeclaration(); |
144 if (fd && fd.isAbstract()) | |
145 error("function %s is abstract", fd.toChars()); | |
146 } | |
147 } | |
148 checkDeprecated(sc, cd); | |
149 if (cd.isNested()) | |
150 { /* We need a 'this' pointer for the nested class. | |
151 * Ensure we have the right one. | |
152 */ | |
153 Dsymbol s = cd.toParent2(); | |
154 ClassDeclaration cdn = s.isClassDeclaration(); | |
155 FuncDeclaration fdn = s.isFuncDeclaration(); | |
156 | |
157 //printf("cd isNested, cdn = %s\n", cdn ? cdn.toChars() : "null"); | |
158 if (cdn) | |
159 { | |
160 if (!cdthis) | |
161 { | |
162 // Supply an implicit 'this' and try again | |
163 thisexp = new ThisExp(loc); | |
164 for (Dsymbol sp = sc.parent; 1; sp = sp.parent) | |
174 | 165 { |
0 | 166 if (!sp) |
167 { | |
168 error("outer class %s 'this' needed to 'new' nested class %s", cdn.toChars(), cd.toChars()); | |
169 break; | |
170 } | |
171 ClassDeclaration cdp = sp.isClassDeclaration(); | |
172 if (!cdp) | |
173 continue; | |
174 if (cdp == cdn || cdn.isBaseOf(cdp, null)) | |
175 break; | |
176 // Add a '.outer' and try again | |
177 thisexp = new DotIdExp(loc, thisexp, Id.outer); | |
178 } | |
179 if (!global.errors) | |
180 goto Lagain; | |
181 } | |
182 if (cdthis) | |
183 { | |
184 //printf("cdthis = %s\n", cdthis.toChars()); | |
185 if (cdthis != cdn && !cdn.isBaseOf(cdthis, null)) | |
186 error("'this' for nested class must be of type %s, not %s", cdn.toChars(), thisexp.type.toChars()); | |
187 } | |
188 else | |
189 { | |
190 static if (false) { | |
191 for (Dsymbol *sf = sc.func; 1; sf= sf.toParent2().isFuncDeclaration()) | |
192 { | |
193 if (!sf) | |
194 { | |
195 error("outer class %s 'this' needed to 'new' nested class %s", cdn.toChars(), cd.toChars()); | |
196 break; | |
197 } | |
198 printf("sf = %s\n", sf.toChars()); | |
199 AggregateDeclaration *ad = sf.isThis(); | |
200 if (ad && (ad == cdn || cdn.isBaseOf(ad.isClassDeclaration(), null))) | |
201 break; | |
202 } | |
203 } | |
204 } | |
205 } | |
206 ///static if (true) { | |
207 else if (thisexp) | |
208 error("e.new is only for allocating nested classes"); | |
209 else if (fdn) | |
210 { | |
211 // make sure the parent context fdn of cd is reachable from sc | |
212 for (Dsymbol sp = sc.parent; 1; sp = sp.parent) | |
213 { | |
214 if (fdn is sp) | |
215 break; | |
216 FuncDeclaration fsp = sp ? sp.isFuncDeclaration() : null; | |
217 if (!sp || (fsp && fsp.isStatic())) | |
218 { | |
219 error("outer function context of %s is needed to 'new' nested class %s", fdn.toPrettyChars(), cd.toPrettyChars()); | |
220 break; | |
221 } | |
222 } | |
223 } | |
224 ///} else { | |
225 /// else if (fdn) | |
174 | 226 /// { |
0 | 227 /// /* The nested class cd is nested inside a function, |
228 /// * we'll let getEthis() look for errors. | |
229 /// */ | |
230 /// //printf("nested class %s is nested inside function %s, we're in %s\n", cd.toChars(), fdn.toChars(), sc.func.toChars()); | |
231 /// if (thisexp) | |
232 /// // Because thisexp cannot be a function frame pointer | |
233 /// error("e.new is only for allocating nested classes"); | |
234 /// } | |
235 ///} | |
236 else | |
237 assert(0); | |
238 } | |
239 else if (thisexp) | |
240 error("e.new is only for allocating nested classes"); | |
241 | |
242 FuncDeclaration f = null; | |
243 if (cd.ctor) | |
244 f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0); | |
245 if (f) | |
246 { | |
247 checkDeprecated(sc, f); | |
248 member = f.isCtorDeclaration(); | |
249 assert(member); | |
250 | |
251 cd.accessCheck(loc, sc, member); | |
252 | |
253 tf = cast(TypeFunction)f.type; | |
254 | |
255 if (!arguments) | |
256 arguments = new Expressions(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
257 functionParameters(loc, sc, tf, arguments); |
0 | 258 } |
259 else | |
260 { | |
261 if (arguments && arguments.dim) | |
262 error("no constructor for %s", cd.toChars()); | |
263 } | |
264 | |
265 if (cd.aggNew) | |
266 { | |
267 // Prepend the size argument to newargs[] | |
268 Expression e = new IntegerExp(loc, cd.size(loc), Type.tsize_t); | |
269 if (!newargs) | |
270 newargs = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
271 newargs.shift(e); |
0 | 272 |
273 f = cd.aggNew.overloadResolve(loc, null, newargs); | |
274 allocator = f.isNewDeclaration(); | |
275 assert(allocator); | |
276 | |
277 tf = cast(TypeFunction)f.type; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
278 functionParameters(loc, sc, tf, newargs); |
0 | 279 } |
280 else | |
281 { | |
282 if (newargs && newargs.dim) | |
283 error("no allocator for %s", cd.toChars()); | |
284 } | |
285 } | |
286 else if (tb.ty == Tstruct) | |
287 { | |
288 TypeStruct ts = cast(TypeStruct)tb; | |
289 StructDeclaration sd = ts.sym; | |
290 TypeFunction tf; | |
291 | |
292 FuncDeclaration f = null; | |
293 if (sd.ctor) | |
294 f = resolveFuncCall(sc, loc, sd.ctor, null, null, arguments, 0); | |
295 if (f) | |
296 { | |
297 checkDeprecated(sc, f); | |
298 member = f.isCtorDeclaration(); | |
299 assert(member); | |
300 | |
301 sd.accessCheck(loc, sc, member); | |
302 | |
303 tf = cast(TypeFunction)f.type; | |
304 // type = tf.next; | |
305 | |
306 if (!arguments) | |
307 arguments = new Expressions(); | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
308 functionParameters(loc, sc, tf, arguments); |
0 | 309 } |
310 else | |
311 { | |
312 if (arguments && arguments.dim) | |
313 error("no constructor for %s", sd.toChars()); | |
314 } | |
315 | |
316 if (sd.aggNew) | |
317 { | |
318 // Prepend the uint size argument to newargs[] | |
319 Expression e = new IntegerExp(loc, sd.size(loc), Type.tuns32); | |
320 if (!newargs) | |
321 newargs = new Expressions(); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
322 newargs.shift(e); |
0 | 323 |
324 f = sd.aggNew.overloadResolve(loc, null, newargs); | |
325 allocator = f.isNewDeclaration(); | |
326 assert(allocator); | |
327 | |
328 tf = cast(TypeFunction)f.type; | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
123
diff
changeset
|
329 functionParameters(loc, sc, tf, newargs); |
0 | 330 static if (false) { |
331 e = new VarExp(loc, f); | |
332 e = new CallExp(loc, e, newargs); | |
333 e = e.semantic(sc); | |
334 e.type = type.pointerTo(); | |
335 return e; | |
336 } | |
337 } | |
338 else | |
339 { | |
340 if (newargs && newargs.dim) | |
341 error("no allocator for %s", sd.toChars()); | |
342 } | |
343 | |
344 type = type.pointerTo(); | |
345 } | |
346 else if (tb.ty == Tarray && (arguments && arguments.dim)) | |
347 { | |
348 for (size_t j = 0; j < arguments.dim; j++) | |
349 { | |
350 if (tb.ty != Tarray) | |
174 | 351 { |
0 | 352 error("too many arguments for array"); |
353 arguments.dim = i; | |
354 break; | |
355 } | |
356 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
357 auto arg = arguments[j]; |
0 | 358 arg = resolveProperties(sc, arg); |
359 arg = arg.implicitCastTo(sc, Type.tsize_t); | |
360 arg = arg.optimize(WANTvalue); | |
361 if (arg.op == TOKint64 && cast(long)arg.toInteger() < 0) | |
362 error("negative array index %s", arg.toChars()); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
72
diff
changeset
|
363 arguments[j] = arg; |
0 | 364 tb = (cast(TypeDArray)tb).next.toBasetype(); |
365 } | |
366 } | |
367 else if (tb.isscalar()) | |
368 { | |
369 if (arguments && arguments.dim) | |
370 error("no constructor for %s", type.toChars()); | |
371 | |
372 type = type.pointerTo(); | |
373 } | |
374 else | |
375 { | |
376 error("new can only create structs, dynamic arrays or class objects, not %s's", type.toChars()); | |
377 type = type.pointerTo(); | |
378 } | |
379 | |
380 //printf("NewExp: '%s'\n", toChars()); | |
381 //printf("NewExp:type '%s'\n", type.toChars()); | |
382 | |
383 return this; | |
384 } | |
179 | 385 |
386 Expression interpret(InterState istate) | |
387 { | |
388 version (LOG) { | |
389 writef("NewExp::interpret() %s\n", toChars()); | |
390 } | |
391 if (newtype.ty == Tarray && arguments && arguments.dim == 1) | |
392 { | |
393 Expression lenExpr = arguments[0].interpret(istate); | |
394 if (lenExpr is EXP_CANT_INTERPRET) | |
395 return EXP_CANT_INTERPRET; | |
396 return createBlockDuplicatedArrayLiteral(newtype, newtype.defaultInitLiteral(Loc(0)), cast(uint)lenExpr.toInteger()); | |
397 } | |
398 error("Cannot interpret %s at compile time", toChars()); | |
399 return EXP_CANT_INTERPRET; | |
400 | |
401 } | |
0 | 402 |
72 | 403 override Expression optimize(int result) |
0 | 404 { |
405 if (thisexp) | |
406 thisexp = thisexp.optimize(WANTvalue); | |
407 | |
408 // Optimize parameters | |
409 if (newargs) | |
410 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
411 foreach (ref Expression e; newargs) |
174 | 412 { |
0 | 413 e = e.optimize(WANTvalue); |
414 } | |
415 } | |
416 | |
417 if (arguments) | |
418 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
419 foreach (ref Expression e; arguments) |
174 | 420 { |
0 | 421 e = e.optimize(WANTvalue); |
422 } | |
423 } | |
424 return this; | |
425 } | |
426 | |
72 | 427 override elem* toElem(IRState* irs) |
0 | 428 { |
429 elem* e; | |
430 Type t; | |
431 Type ectype; | |
432 | |
433 //printf("NewExp.toElem() %s\n", toChars()); | |
434 t = type.toBasetype(); | |
435 //printf("\ttype = %s\n", t.toChars()); | |
436 //if (member) | |
437 //printf("\tmember = %s\n", member.toChars()); | |
438 if (t.ty == Tclass) | |
439 { | |
440 Symbol* csym; | |
441 | |
442 t = newtype.toBasetype(); | |
443 assert(t.ty == Tclass); | |
444 TypeClass tclass = cast(TypeClass)t; | |
445 ClassDeclaration cd = tclass.sym; | |
446 | |
447 /* Things to do: | |
448 * 1) ex: call allocator | |
449 * 2) ey: set vthis for nested classes | |
450 * 3) ez: call constructor | |
451 */ | |
452 | |
453 elem *ex = null; | |
454 elem *ey = null; | |
455 elem *ez = null; | |
456 | |
457 if (allocator || onstack) | |
174 | 458 { |
0 | 459 elem *ei; |
460 Symbol *si; | |
461 | |
462 if (onstack) | |
463 { | |
464 /* Create an instance of the class on the stack, | |
465 * and call it stmp. | |
466 * Set ex to be the &stmp. | |
467 */ | |
468 Symbol* s = symbol_calloc(toStringz(tclass.sym.toChars())); | |
469 s.Sclass = SCstruct; | |
470 s.Sstruct = struct_calloc(); | |
471 s.Sstruct.Sflags |= 0; | |
472 s.Sstruct.Salignsize = tclass.sym.alignsize; | |
473 s.Sstruct.Sstructalign = cast(ubyte)tclass.sym.structalign; | |
474 s.Sstruct.Sstructsize = tclass.sym.structsize; | |
475 | |
476 .type* tc = type_alloc(TYstruct); | |
477 tc.Ttag = cast(Classsym*)s; // structure tag name | |
478 tc.Tcount++; | |
479 s.Stype = tc; | |
480 | |
481 Symbol *stmp = symbol_genauto(tc); | |
482 ex = el_ptr(stmp); | |
483 } | |
484 else | |
485 { | |
486 ex = el_var(allocator.toSymbol()); | |
487 ex = callfunc(loc, irs, 1, type, ex, allocator.type, | |
488 allocator, allocator.type, null, newargs); | |
489 } | |
490 | |
491 si = tclass.sym.toInitializer(); | |
492 ei = el_var(si); | |
493 | |
494 if (cd.isNested()) | |
495 { | |
496 ey = el_same(&ex); | |
497 ez = el_copytree(ey); | |
498 } | |
499 else if (member) | |
500 ez = el_same(&ex); | |
501 | |
502 ex = el_una(OPind, TYstruct, ex); | |
503 ex = el_bin(OPstreq, TYnptr, ex, ei); | |
504 ex.Enumbytes = cd.size(loc); | |
505 ex = el_una(OPaddr, TYnptr, ex); | |
506 ectype = tclass; | |
507 } | |
508 else | |
509 { | |
510 csym = cd.toSymbol(); | |
511 ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym)); | |
512 ectype = null; | |
513 | |
514 if (cd.isNested()) | |
515 { | |
516 ey = el_same(&ex); | |
517 ez = el_copytree(ey); | |
518 } | |
519 else if (member) | |
520 ez = el_same(&ex); | |
521 //elem_print(ex); | |
522 //elem_print(ey); | |
523 //elem_print(ez); | |
524 } | |
525 | |
526 if (thisexp) | |
174 | 527 { |
0 | 528 ClassDeclaration cdthis = thisexp.type.isClassHandle(); |
529 assert(cdthis); | |
530 //printf("cd = %s\n", cd.toChars()); | |
531 //printf("cdthis = %s\n", cdthis.toChars()); | |
532 assert(cd.isNested()); | |
533 int offset = 0; | |
534 Dsymbol cdp = cd.toParent2(); // class we're nested in | |
535 elem* ethis; | |
536 | |
537 //printf("member = %p\n", member); | |
538 //printf("cdp = %s\n", cdp.toChars()); | |
539 //printf("cdthis = %s\n", cdthis.toChars()); | |
540 if (cdp != cdthis) | |
174 | 541 { |
0 | 542 int i = cdp.isClassDeclaration().isBaseOf(cdthis, &offset); |
543 assert(i); | |
544 } | |
545 ethis = thisexp.toElem(irs); | |
546 if (offset) | |
547 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset)); | |
548 | |
549 if (!cd.vthis) | |
550 { | |
551 error("forward reference to %s", cd.toChars()); | |
552 } | |
553 else | |
554 { | |
555 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd.vthis.offset)); | |
556 ey = el_una(OPind, TYnptr, ey); | |
557 ey = el_bin(OPeq, TYnptr, ey, ethis); | |
558 } | |
559 //printf("ex: "); elem_print(ex); | |
560 //printf("ey: "); elem_print(ey); | |
561 //printf("ez: "); elem_print(ez); | |
562 } | |
563 else if (cd.isNested()) | |
174 | 564 { |
0 | 565 /* Initialize cd.vthis: |
566 * *(ey + cd.vthis.offset) = this; | |
567 */ | |
568 ey = setEthis(loc, irs, ey, cd); | |
569 } | |
570 | |
571 if (member) | |
572 // Call constructor | |
573 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments); | |
574 | |
575 e = el_combine(ex, ey); | |
576 e = el_combine(e, ez); | |
577 } | |
578 else if (t.ty == Tpointer && t.nextOf().toBasetype().ty == Tstruct) | |
579 { | |
580 Symbol* csym; | |
581 | |
582 t = newtype.toBasetype(); | |
583 assert(t.ty == Tstruct); | |
584 TypeStruct tclass = cast(TypeStruct)t; | |
585 StructDeclaration cd = tclass.sym; | |
586 | |
587 /* Things to do: | |
588 * 1) ex: call allocator | |
589 * 2) ey: set vthis for nested classes | |
590 * 3) ez: call constructor | |
591 */ | |
592 | |
593 elem* ex = null; | |
594 elem* ey = null; | |
595 elem* ez = null; | |
596 | |
597 if (allocator) | |
174 | 598 { |
0 | 599 elem *ei; |
600 Symbol *si; | |
601 | |
602 ex = el_var(allocator.toSymbol()); | |
603 ex = callfunc(loc, irs, 1, type, ex, allocator.type, | |
604 allocator, allocator.type, null, newargs); | |
605 | |
606 si = tclass.sym.toInitializer(); | |
607 ei = el_var(si); | |
608 | |
609 if (cd.isNested()) | |
610 { | |
611 ey = el_same(&ex); | |
612 ez = el_copytree(ey); | |
613 } | |
614 else if (member) | |
615 ez = el_same(&ex); | |
616 | |
617 if (!member) | |
174 | 618 { |
0 | 619 /* Statically intialize with default initializer |
620 */ | |
621 ex = el_una(OPind, TYstruct, ex); | |
622 ex = el_bin(OPstreq, TYnptr, ex, ei); | |
623 ex.Enumbytes = cd.size(loc); | |
624 ex = el_una(OPaddr, TYnptr, ex); | |
625 } | |
626 ectype = tclass; | |
627 } | |
628 else | |
629 { | |
630 ulong elemsize = cd.size(loc); | |
631 | |
632 // call _d_newarrayT(ti, 1) | |
633 e = el_long(TYsize_t, 1); | |
634 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
635 | |
636 int rtl = t.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
637 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
638 | |
639 // The new functions return an array, so convert to a pointer | |
640 // ex . (unsigned)(e >> 32) | |
641 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); | |
642 ex = el_una(OP64_32, TYnptr, e); | |
643 | |
644 ectype = null; | |
645 | |
646 if (cd.isNested()) | |
647 { | |
648 ey = el_same(&ex); | |
649 ez = el_copytree(ey); | |
650 } | |
651 else if (member) | |
652 ez = el_same(&ex); | |
653 //elem_print(ex); | |
654 //elem_print(ey); | |
655 //elem_print(ez); | |
656 } | |
657 | |
658 if (cd.isNested()) | |
174 | 659 { |
0 | 660 /* Initialize cd.vthis: |
661 * *(ey + cd.vthis.offset) = this; | |
662 */ | |
663 ey = setEthis(loc, irs, ey, cd); | |
664 } | |
665 | |
666 if (member) | |
174 | 667 { |
0 | 668 // Call constructor |
669 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments); | |
670 version (STRUCTTHISREF) { | |
671 /* Structs return a ref, which gets automatically dereferenced. | |
672 * But we want a pointer to the instance. | |
673 */ | |
674 ez = el_una(OPaddr, TYnptr, ez); | |
675 } | |
676 } | |
677 | |
678 e = el_combine(ex, ey); | |
679 e = el_combine(e, ez); | |
680 } | |
681 else if (t.ty == Tarray) | |
682 { | |
683 TypeDArray tda = cast(TypeDArray)t; | |
684 | |
685 assert(arguments && arguments.dim >= 1); | |
686 if (arguments.dim == 1) | |
174 | 687 { |
0 | 688 // Single dimension array allocations |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
689 auto arg = arguments[0]; // gives array length |
0 | 690 e = arg.toElem(irs); |
691 ulong elemsize = tda.next.size(); | |
692 | |
693 // call _d_newT(ti, arg) | |
694 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
695 int rtl = tda.next.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
696 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
697 } | |
698 else | |
174 | 699 { |
0 | 700 // Multidimensional array allocations |
701 e = el_long(TYint, arguments.dim); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
702 foreach (Expression arg; arguments) |
0 | 703 { |
704 e = el_param(arg.toElem(irs), e); | |
705 assert(t.ty == Tarray); | |
706 t = t.nextOf(); | |
707 assert(t); | |
708 } | |
709 | |
710 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
711 | |
712 int rtl = t.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT; | |
713 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
714 } | |
715 } | |
716 else if (t.ty == Tpointer) | |
717 { | |
718 TypePointer tp = cast(TypePointer)t; | |
719 ulong elemsize = tp.next.size(); | |
720 Expression di = tp.next.defaultInit(Loc(0)); | |
721 ulong disize = di.type.size(); | |
722 | |
723 // call _d_newarrayT(ti, 1) | |
724 e = el_long(TYsize_t, 1); | |
725 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
726 | |
727 int rtl = tp.next.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
728 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
729 | |
730 // The new functions return an array, so convert to a pointer | |
731 // e . (unsigned)(e >> 32) | |
732 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); | |
733 e = el_una(OP64_32, t.totym(), e); | |
734 } | |
735 else | |
736 { | |
737 assert(0); | |
738 } | |
739 | |
740 el_setLoc(e,loc); | |
741 return e; | |
742 } | |
743 | |
72 | 744 override bool checkSideEffect(int flag) |
0 | 745 { |
123 | 746 return true; |
0 | 747 } |
748 | |
72 | 749 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 750 { |
174 | 751 int i; |
752 | |
753 if (thisexp) | |
754 { | |
755 expToCBuffer(buf, hgs, thisexp, PREC.PREC_primary); | |
756 buf.writeByte('.'); | |
757 } | |
758 buf.writestring("new "); | |
759 if (newargs && newargs.dim) | |
760 { | |
761 buf.writeByte('('); | |
762 argsToCBuffer(buf, newargs, hgs); | |
763 buf.writeByte(')'); | |
764 } | |
765 newtype.toCBuffer(buf, null, hgs); | |
766 if (arguments && arguments.dim) | |
767 { | |
768 buf.writeByte('('); | |
769 argsToCBuffer(buf, arguments, hgs); | |
770 buf.writeByte(')'); | |
771 } | |
0 | 772 } |
773 | |
72 | 774 override void scanForNestedRef(Scope sc) |
0 | 775 { |
72 | 776 //printf("NewExp.scanForNestedRef(Scope *sc): %s\n", toChars()); |
777 | |
778 if (thisexp) | |
779 thisexp.scanForNestedRef(sc); | |
780 arrayExpressionScanForNestedRef(sc, newargs); | |
64 | 781 arrayExpressionScanForNestedRef(sc, arguments); |
0 | 782 } |
783 | |
784 version (DMDV2) { | |
72 | 785 override bool canThrow() |
0 | 786 { |
787 return 1; | |
72 | 788 } |
0 | 789 } |
174 | 790 |
0 | 791 //int inlineCost(InlineCostState *ics); |
792 | |
72 | 793 override Expression doInline(InlineDoState ids) |
0 | 794 { |
795 //printf("NewExp.doInline(): %s\n", toChars()); | |
796 NewExp ne = cast(NewExp)copy(); | |
797 | |
798 if (thisexp) | |
799 ne.thisexp = thisexp.doInline(ids); | |
800 ne.newargs = arrayExpressiondoInline(ne.newargs, ids); | |
801 ne.arguments = arrayExpressiondoInline(ne.arguments, ids); | |
802 return ne; | |
72 | 803 } |
174 | 804 |
0 | 805 //Expression inlineScan(InlineScanState *iss); |
806 } | |
807 |