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 {
|
53
|
71 return new NewExp(loc,
|
|
72 thisexp ? thisexp.syntaxCopy() : null,
|
|
73 arraySyntaxCopy(newargs),
|
|
74 newtype.syntaxCopy(), arraySyntaxCopy(arguments));
|
0
|
75 }
|
|
76
|
|
77 Expression semantic(Scope sc)
|
|
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();
|
|
264 newargs.shift(cast(void*)e);
|
|
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();
|
|
315 newargs.shift(cast(void*)e);
|
|
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());
|
|
356 arguments.data[j] = cast(void*) arg;
|
|
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
|
|
379 Expression optimize(int result)
|
|
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);
|
|
392 newargs.data[i] = cast(void*)e;
|
|
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);
|
|
403 arguments.data[i] = cast(void*)e;
|
|
404 }
|
|
405 }
|
|
406 return this;
|
|
407 }
|
|
408
|
|
409 elem* toElem(IRState* irs)
|
|
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
|
|
727 bool checkSideEffect(int flag)
|
|
728 {
|
|
729 assert(false);
|
|
730 }
|
|
731
|
|
732 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
|
733 {
|
|
734 assert(false);
|
|
735 }
|
|
736
|
|
737 void scanForNestedRef(Scope sc)
|
|
738 {
|
|
739 assert(false);
|
|
740 }
|
|
741
|
|
742 version (DMDV2) {
|
|
743 bool canThrow()
|
|
744 {
|
|
745 return 1;
|
|
746 }
|
|
747 }
|
|
748
|
|
749 //int inlineCost(InlineCostState *ics);
|
|
750
|
|
751 Expression doInline(InlineDoState ids)
|
|
752 {
|
|
753 //printf("NewExp.doInline(): %s\n", toChars());
|
|
754 NewExp ne = cast(NewExp)copy();
|
|
755
|
|
756 if (thisexp)
|
|
757 ne.thisexp = thisexp.doInline(ids);
|
|
758 ne.newargs = arrayExpressiondoInline(ne.newargs, ids);
|
|
759 ne.arguments = arrayExpressiondoInline(ne.arguments, ids);
|
|
760 return ne;
|
|
761 }
|
|
762
|
|
763 //Expression inlineScan(InlineScanState *iss);
|
|
764 }
|
|
765
|