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