0
|
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
|