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