Mercurial > projects > ddmd
annotate dmd/NewExp.d @ 90:39648eb578f6
more Expressions work
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 30 Aug 2010 20:27:56 +0100 |
parents | be2ab491772e |
children | e28b18c23469 |
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 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
350 auto arg = arguments[j]; |
0 | 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 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
387 foreach (ref Expression e; newargs) |
0 | 388 { |
389 e = e.optimize(WANTvalue); | |
390 } | |
391 } | |
392 | |
393 if (arguments) | |
394 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
395 foreach (ref Expression e; arguments) |
0 | 396 { |
397 e = e.optimize(WANTvalue); | |
398 } | |
399 } | |
400 return this; | |
401 } | |
402 | |
72 | 403 override elem* toElem(IRState* irs) |
0 | 404 { |
405 elem* e; | |
406 Type t; | |
407 Type ectype; | |
408 | |
409 //printf("NewExp.toElem() %s\n", toChars()); | |
410 t = type.toBasetype(); | |
411 //printf("\ttype = %s\n", t.toChars()); | |
412 //if (member) | |
413 //printf("\tmember = %s\n", member.toChars()); | |
414 if (t.ty == Tclass) | |
415 { | |
416 Symbol* csym; | |
417 | |
418 t = newtype.toBasetype(); | |
419 assert(t.ty == Tclass); | |
420 TypeClass tclass = cast(TypeClass)t; | |
421 ClassDeclaration cd = tclass.sym; | |
422 | |
423 /* Things to do: | |
424 * 1) ex: call allocator | |
425 * 2) ey: set vthis for nested classes | |
426 * 3) ez: call constructor | |
427 */ | |
428 | |
429 elem *ex = null; | |
430 elem *ey = null; | |
431 elem *ez = null; | |
432 | |
433 if (allocator || onstack) | |
434 { | |
435 elem *ei; | |
436 Symbol *si; | |
437 | |
438 if (onstack) | |
439 { | |
440 /* Create an instance of the class on the stack, | |
441 * and call it stmp. | |
442 * Set ex to be the &stmp. | |
443 */ | |
444 Symbol* s = symbol_calloc(toStringz(tclass.sym.toChars())); | |
445 s.Sclass = SCstruct; | |
446 s.Sstruct = struct_calloc(); | |
447 s.Sstruct.Sflags |= 0; | |
448 s.Sstruct.Salignsize = tclass.sym.alignsize; | |
449 s.Sstruct.Sstructalign = cast(ubyte)tclass.sym.structalign; | |
450 s.Sstruct.Sstructsize = tclass.sym.structsize; | |
451 | |
452 .type* tc = type_alloc(TYstruct); | |
453 tc.Ttag = cast(Classsym*)s; // structure tag name | |
454 tc.Tcount++; | |
455 s.Stype = tc; | |
456 | |
457 Symbol *stmp = symbol_genauto(tc); | |
458 ex = el_ptr(stmp); | |
459 } | |
460 else | |
461 { | |
462 ex = el_var(allocator.toSymbol()); | |
463 ex = callfunc(loc, irs, 1, type, ex, allocator.type, | |
464 allocator, allocator.type, null, newargs); | |
465 } | |
466 | |
467 si = tclass.sym.toInitializer(); | |
468 ei = el_var(si); | |
469 | |
470 if (cd.isNested()) | |
471 { | |
472 ey = el_same(&ex); | |
473 ez = el_copytree(ey); | |
474 } | |
475 else if (member) | |
476 ez = el_same(&ex); | |
477 | |
478 ex = el_una(OPind, TYstruct, ex); | |
479 ex = el_bin(OPstreq, TYnptr, ex, ei); | |
480 ex.Enumbytes = cd.size(loc); | |
481 ex = el_una(OPaddr, TYnptr, ex); | |
482 ectype = tclass; | |
483 } | |
484 else | |
485 { | |
486 csym = cd.toSymbol(); | |
487 ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym)); | |
488 ectype = null; | |
489 | |
490 if (cd.isNested()) | |
491 { | |
492 ey = el_same(&ex); | |
493 ez = el_copytree(ey); | |
494 } | |
495 else if (member) | |
496 ez = el_same(&ex); | |
497 //elem_print(ex); | |
498 //elem_print(ey); | |
499 //elem_print(ez); | |
500 } | |
501 | |
502 if (thisexp) | |
503 { | |
504 ClassDeclaration cdthis = thisexp.type.isClassHandle(); | |
505 assert(cdthis); | |
506 //printf("cd = %s\n", cd.toChars()); | |
507 //printf("cdthis = %s\n", cdthis.toChars()); | |
508 assert(cd.isNested()); | |
509 int offset = 0; | |
510 Dsymbol cdp = cd.toParent2(); // class we're nested in | |
511 elem* ethis; | |
512 | |
513 //printf("member = %p\n", member); | |
514 //printf("cdp = %s\n", cdp.toChars()); | |
515 //printf("cdthis = %s\n", cdthis.toChars()); | |
516 if (cdp != cdthis) | |
517 { | |
518 int i = cdp.isClassDeclaration().isBaseOf(cdthis, &offset); | |
519 assert(i); | |
520 } | |
521 ethis = thisexp.toElem(irs); | |
522 if (offset) | |
523 ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset)); | |
524 | |
525 if (!cd.vthis) | |
526 { | |
527 error("forward reference to %s", cd.toChars()); | |
528 } | |
529 else | |
530 { | |
531 ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd.vthis.offset)); | |
532 ey = el_una(OPind, TYnptr, ey); | |
533 ey = el_bin(OPeq, TYnptr, ey, ethis); | |
534 } | |
535 //printf("ex: "); elem_print(ex); | |
536 //printf("ey: "); elem_print(ey); | |
537 //printf("ez: "); elem_print(ez); | |
538 } | |
539 else if (cd.isNested()) | |
540 { | |
541 /* Initialize cd.vthis: | |
542 * *(ey + cd.vthis.offset) = this; | |
543 */ | |
544 ey = setEthis(loc, irs, ey, cd); | |
545 } | |
546 | |
547 if (member) | |
548 // Call constructor | |
549 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments); | |
550 | |
551 e = el_combine(ex, ey); | |
552 e = el_combine(e, ez); | |
553 } | |
554 else if (t.ty == Tpointer && t.nextOf().toBasetype().ty == Tstruct) | |
555 { | |
556 Symbol* csym; | |
557 | |
558 t = newtype.toBasetype(); | |
559 assert(t.ty == Tstruct); | |
560 TypeStruct tclass = cast(TypeStruct)t; | |
561 StructDeclaration cd = tclass.sym; | |
562 | |
563 /* Things to do: | |
564 * 1) ex: call allocator | |
565 * 2) ey: set vthis for nested classes | |
566 * 3) ez: call constructor | |
567 */ | |
568 | |
569 elem* ex = null; | |
570 elem* ey = null; | |
571 elem* ez = null; | |
572 | |
573 if (allocator) | |
574 { | |
575 elem *ei; | |
576 Symbol *si; | |
577 | |
578 ex = el_var(allocator.toSymbol()); | |
579 ex = callfunc(loc, irs, 1, type, ex, allocator.type, | |
580 allocator, allocator.type, null, newargs); | |
581 | |
582 si = tclass.sym.toInitializer(); | |
583 ei = el_var(si); | |
584 | |
585 if (cd.isNested()) | |
586 { | |
587 ey = el_same(&ex); | |
588 ez = el_copytree(ey); | |
589 } | |
590 else if (member) | |
591 ez = el_same(&ex); | |
592 | |
593 if (!member) | |
594 { | |
595 /* Statically intialize with default initializer | |
596 */ | |
597 ex = el_una(OPind, TYstruct, ex); | |
598 ex = el_bin(OPstreq, TYnptr, ex, ei); | |
599 ex.Enumbytes = cd.size(loc); | |
600 ex = el_una(OPaddr, TYnptr, ex); | |
601 } | |
602 ectype = tclass; | |
603 } | |
604 else | |
605 { | |
606 ulong elemsize = cd.size(loc); | |
607 | |
608 // call _d_newarrayT(ti, 1) | |
609 e = el_long(TYsize_t, 1); | |
610 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
611 | |
612 int rtl = t.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
613 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
614 | |
615 // The new functions return an array, so convert to a pointer | |
616 // ex . (unsigned)(e >> 32) | |
617 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); | |
618 ex = el_una(OP64_32, TYnptr, e); | |
619 | |
620 ectype = null; | |
621 | |
622 if (cd.isNested()) | |
623 { | |
624 ey = el_same(&ex); | |
625 ez = el_copytree(ey); | |
626 } | |
627 else if (member) | |
628 ez = el_same(&ex); | |
629 //elem_print(ex); | |
630 //elem_print(ey); | |
631 //elem_print(ez); | |
632 } | |
633 | |
634 if (cd.isNested()) | |
635 { | |
636 /* Initialize cd.vthis: | |
637 * *(ey + cd.vthis.offset) = this; | |
638 */ | |
639 ey = setEthis(loc, irs, ey, cd); | |
640 } | |
641 | |
642 if (member) | |
643 { | |
644 // Call constructor | |
645 ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments); | |
646 version (STRUCTTHISREF) { | |
647 /* Structs return a ref, which gets automatically dereferenced. | |
648 * But we want a pointer to the instance. | |
649 */ | |
650 ez = el_una(OPaddr, TYnptr, ez); | |
651 } | |
652 } | |
653 | |
654 e = el_combine(ex, ey); | |
655 e = el_combine(e, ez); | |
656 } | |
657 else if (t.ty == Tarray) | |
658 { | |
659 TypeDArray tda = cast(TypeDArray)t; | |
660 | |
661 assert(arguments && arguments.dim >= 1); | |
662 if (arguments.dim == 1) | |
663 { | |
664 // Single dimension array allocations | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
665 auto arg = arguments[0]; // gives array length |
0 | 666 e = arg.toElem(irs); |
667 ulong elemsize = tda.next.size(); | |
668 | |
669 // call _d_newT(ti, arg) | |
670 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
671 int rtl = tda.next.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
672 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
673 } | |
674 else | |
675 { | |
676 // Multidimensional array allocations | |
677 e = el_long(TYint, arguments.dim); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
678 foreach (Expression arg; arguments) |
0 | 679 { |
680 e = el_param(arg.toElem(irs), e); | |
681 assert(t.ty == Tarray); | |
682 t = t.nextOf(); | |
683 assert(t); | |
684 } | |
685 | |
686 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
687 | |
688 int rtl = t.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT; | |
689 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
690 } | |
691 } | |
692 else if (t.ty == Tpointer) | |
693 { | |
694 TypePointer tp = cast(TypePointer)t; | |
695 ulong elemsize = tp.next.size(); | |
696 Expression di = tp.next.defaultInit(Loc(0)); | |
697 ulong disize = di.type.size(); | |
698 | |
699 // call _d_newarrayT(ti, 1) | |
700 e = el_long(TYsize_t, 1); | |
701 e = el_param(e, type.getTypeInfo(null).toElem(irs)); | |
702 | |
703 int rtl = tp.next.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; | |
704 e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); | |
705 | |
706 // The new functions return an array, so convert to a pointer | |
707 // e . (unsigned)(e >> 32) | |
708 e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); | |
709 e = el_una(OP64_32, t.totym(), e); | |
710 } | |
711 else | |
712 { | |
713 assert(0); | |
714 } | |
715 | |
716 el_setLoc(e,loc); | |
717 return e; | |
718 } | |
719 | |
72 | 720 override bool checkSideEffect(int flag) |
0 | 721 { |
722 assert(false); | |
723 } | |
724 | |
72 | 725 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 726 { |
727 assert(false); | |
728 } | |
729 | |
72 | 730 override void scanForNestedRef(Scope sc) |
0 | 731 { |
72 | 732 //printf("NewExp.scanForNestedRef(Scope *sc): %s\n", toChars()); |
733 | |
734 if (thisexp) | |
735 thisexp.scanForNestedRef(sc); | |
736 arrayExpressionScanForNestedRef(sc, newargs); | |
64 | 737 arrayExpressionScanForNestedRef(sc, arguments); |
0 | 738 } |
739 | |
740 version (DMDV2) { | |
72 | 741 override bool canThrow() |
0 | 742 { |
743 return 1; | |
72 | 744 } |
0 | 745 } |
72 | 746 |
0 | 747 //int inlineCost(InlineCostState *ics); |
748 | |
72 | 749 override Expression doInline(InlineDoState ids) |
0 | 750 { |
751 //printf("NewExp.doInline(): %s\n", toChars()); | |
752 NewExp ne = cast(NewExp)copy(); | |
753 | |
754 if (thisexp) | |
755 ne.thisexp = thisexp.doInline(ids); | |
756 ne.newargs = arrayExpressiondoInline(ne.newargs, ids); | |
757 ne.arguments = arrayExpressiondoInline(ne.arguments, ids); | |
758 return ne; | |
72 | 759 } |
760 | |
0 | 761 //Expression inlineScan(InlineScanState *iss); |
762 } | |
763 |