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