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