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