comparison dmd/codegen/Util.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 7427ded8caf7
comparison
equal deleted inserted replaced
-1:000000000000 0:10317f0c89a5
1 module dmd.codegen.Util;
2
3 import dmd.Loc;
4 import dmd.IRState;
5 import dmd.Type;
6 import dmd.Array;
7 import dmd.Dsymbol;
8 import dmd.FuncDeclaration;
9 import dmd.Identifier;
10 import dmd.RET;
11 import dmd.TY;
12 import dmd.LINK;
13 import dmd.Expression;
14 import dmd.Argument;
15 import dmd.STC;
16 import dmd.Global;
17 import dmd.InterfaceDeclaration;
18 import dmd.AggregateDeclaration;
19 import dmd.AttribDeclaration;
20 import dmd.TupleDeclaration;
21 import dmd.StructDeclaration;
22 import dmd.VarDeclaration;
23 import dmd.ClassDeclaration;
24 import dmd.TemplateMixin;
25 import dmd.TypedefDeclaration;
26 import dmd.ExpInitializer;
27 import dmd.TypeFunction;
28 import dmd.TypeStruct;
29 import dmd.TypeSArray;
30 import dmd.TOK;
31 import dmd.Util;
32 import dmd.LabelStatement;
33 import dmd.DsymbolExp;
34 import dmd.LabelDsymbol;
35 import dmd.backend.elem;
36 import dmd.backend.TYPE;
37 import dmd.backend.Util;
38 import dmd.backend.Classsym;
39 import dmd.backend.SC;
40 import dmd.backend.FL;
41 import dmd.backend.SFL;
42 import dmd.backend.STR;
43 import dmd.backend.TYM;
44 import dmd.backend.TF;
45 import dmd.backend.OPER;
46 import dmd.backend.mTYman;
47 import dmd.backend.TYFL;
48 import dmd.backend.mTY;
49 import dmd.backend.Symbol;
50 import dmd.backend.Blockx;
51 import dmd.backend.RTLSYM;
52 import dmd.backend.block;
53 import dmd.backend.LIST;
54
55 import std.string;
56 import core.stdc.string;
57
58 /************************************
59 * Call a function.
60 */
61
62 elem* callfunc(Loc loc,
63 IRState* irs,
64 int directcall, // 1: don't do virtual call
65 Type tret, // return type
66 elem *ec, // evaluates to function address
67 Type ectype, // original type of ec
68 FuncDeclaration fd, // if !=null, this is the function being called
69 Type t, // TypeDelegate or TypeFunction for this function
70 elem* ehidden, // if !=null, this is the 'hidden' argument
71 Array arguments)
72 {
73 elem* ep;
74 elem* e;
75 elem* ethis = null;
76 elem* eside = null;
77 int i;
78 tym_t ty;
79 tym_t tyret;
80 RET retmethod;
81 int reverse;
82 TypeFunction tf;
83 OPER op;
84
85 static if (false) {
86 printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n",
87 directcall, tret.toChars(), ec, fd);
88 printf("ec: "); elem_print(ec);
89 if (fd)
90 printf("fd = '%s'\n", fd.toChars());
91 }
92
93 t = t.toBasetype();
94 if (t.ty == TY.Tdelegate)
95 {
96 // A delegate consists of:
97 // { Object *this; Function *funcptr; }
98 assert(!fd);
99 assert(t.nextOf().ty == TY.Tfunction);
100 tf = cast(TypeFunction)t.nextOf();
101 ethis = ec;
102 ec = el_same(&ethis);
103 ethis = el_una(OPER.OP64_32, TYM.TYnptr, ethis); // get this
104 ec = array_toPtr(t, ec); // get funcptr
105 ec = el_una(OPER.OPind, tf.totym(), ec);
106 }
107 else
108 {
109 assert(t.ty == TY.Tfunction);
110 tf = cast(TypeFunction)t;
111 }
112
113 retmethod = tf.retStyle();
114 ty = ec.Ety;
115 if (fd)
116 ty = fd.toSymbol().Stype.Tty;
117 reverse = tyrevfunc(ty);
118 ep = null;
119 if (arguments)
120 {
121 // j=1 if _arguments[] is first argument
122 int j = (tf.linkage == LINK.LINKd && tf.varargs == 1);
123
124 for (i = 0; i < arguments.dim ; i++)
125 {
126 Expression arg;
127 elem* ea;
128
129 arg = cast(Expression)arguments.data[i];
130 //printf("\targ[%d]: %s\n", i, arg.toChars());
131
132 size_t nparams = Argument.dim(tf.parameters);
133 if (i - j < nparams && i >= j)
134 {
135 Argument p = Argument.getNth(tf.parameters, i - j);
136
137 if (p.storageClass & (STC.STCout | STC.STCref))
138 {
139 // Convert argument to a pointer,
140 // use AddrExp.toElem()
141 Expression ae = arg.addressOf(null);
142 ea = ae.toElem(irs);
143 goto L1;
144 }
145 }
146 ea = arg.toElem(irs);
147 L1:
148 if (tybasic(ea.Ety) == TYM.TYstruct)
149 {
150 ea = el_una(OPER.OPstrpar, TYM.TYstruct, ea);
151 ea.Enumbytes = ea.E1.Enumbytes;
152 assert(ea.Enumbytes);
153 }
154 if (reverse)
155 ep = el_param(ep,ea);
156 else
157 ep = el_param(ea,ep);
158 }
159 }
160
161 if (retmethod == RET.RETstack)
162 {
163 if (!ehidden)
164 {
165 // Don't have one, so create one
166 type* tt;
167
168 if (tf.next.toBasetype().ty == TY.Tstruct)
169 tt = tf.next.toCtype();
170 else
171 tt = type_fake(tf.next.totym());
172
173 Symbol* stmp = symbol_genauto(tt);
174 ehidden = el_ptr(stmp);
175 }
176 if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) && tf.linkage != LINK.LINKd) {
177 ; // ehidden goes last on Linux/OSX C++
178 } else {
179 if (ep)
180 {
181 static if (false) { // BUG: implement
182 if (reverse && type_mangle(tfunc) == mTYman.mTYman_cpp) {
183 ep = el_param(ehidden,ep);
184 } else {
185 ep = el_param(ep,ehidden);
186 }
187 } else {
188 ep = el_param(ep,ehidden);
189 }
190 }
191 else
192 ep = ehidden;
193 ehidden = null;
194 }
195 }
196
197 if (fd && fd.isMember2())
198 {
199 InterfaceDeclaration intd;
200 Symbol* sfunc;
201 AggregateDeclaration ad;
202
203 ad = fd.isThis();
204 if (ad)
205 {
206 ethis = ec;
207 if (ad.isStructDeclaration() && tybasic(ec.Ety) != TYM.TYnptr)
208 {
209 ethis = addressElem(ec, ectype);
210 }
211 }
212 else
213 {
214 // Evaluate ec for side effects
215 eside = ec;
216 }
217 sfunc = fd.toSymbol();
218
219 if (!fd.isVirtual() ||
220 directcall || // BUG: fix
221 fd.isFinal())
222 {
223 // make static call
224 ec = el_var(sfunc);
225 }
226 else
227 {
228 // make virtual call
229 elem* ev;
230 uint vindex;
231
232 assert(ethis);
233 ev = el_same(&ethis);
234 ev = el_una(OPER.OPind, TYM.TYnptr, ev);
235 vindex = fd.vtblIndex;
236
237 // Build *(ev + vindex * 4)
238 ec = el_bin(OPER.OPadd, TYM.TYnptr, ev, el_long(TYM.TYint, vindex * 4));
239 ec = el_una(OPER.OPind, TYM.TYnptr, ec);
240 ec = el_una(OPER.OPind, tybasic(sfunc.Stype.Tty), ec);
241 }
242 }
243 else if (fd && fd.isNested())
244 {
245 assert(!ethis);
246 ethis = getEthis(Loc(0), irs, fd);
247 }
248
249 ep = el_param(ep, ethis);
250 if (ehidden)
251 ep = el_param(ep, ehidden); // if ehidden goes last
252
253 tyret = tret.totym();
254
255 // Look for intrinsic functions
256 if (ec.Eoper == OPER.OPvar && (op = intrinsic_oper(ec.EV.sp.Vsym.Sident.ptr)) != OPER.OPMAX)
257 {
258 el_free(ec);
259 if (OTbinary(op))
260 {
261 ep.Eoper = op;
262 ep.Ety = tyret;
263 e = ep;
264 if (op == OPER.OPscale)
265 {
266 elem *et = e.E1;
267 e.E1() = el_una(OPER.OPd_ld, TYM.TYldouble, e.E1);
268 e.E1() = el_una(OPER.OPs32_d, TYM.TYdouble, e.E2);
269 e.E2() = et;
270 }
271 else if (op == OPER.OPyl2x || op == OPER.OPyl2xp1)
272 {
273 elem *et = e.E1;
274 e.E1() = e.E2;
275 e.E2() = et;
276 }
277 }
278 else
279 e = el_una(op,tyret,ep);
280 }
281 else if (ep)
282 e = el_bin(tf.ispure ? OPER.OPcallns : OPER.OPcall, tyret, ec, ep);
283 else
284 e = el_una(tf.ispure ? OPER.OPucallns : OPER.OPucall, tyret, ec);
285
286 if (retmethod == RET.RETstack)
287 {
288 e.Ety = TYM.TYnptr;
289 e = el_una(OPER.OPind, tyret, e);
290 }
291
292 version (DMDV2) {
293 if (tf.isref)
294 {
295 e.Ety = TYM.TYnptr;
296 e = el_una(OPER.OPind, tyret, e);
297 }
298 }
299
300 if (tybasic(tyret) == TYM.TYstruct)
301 {
302 e.Enumbytes = cast(uint)tret.size();
303 }
304
305 e = el_combine(eside, e);
306 return e;
307 }
308
309 /**************************************
310 * Fake a struct symbol.
311 */
312
313 Classsym* fake_classsym(Identifier id)
314 {
315 TYPE* t;
316 Classsym* scc;
317
318 scc = cast(Classsym*)symbol_calloc(toStringz(id.toChars()));
319 scc.Sclass = SC.SCstruct;
320 scc.Sstruct = struct_calloc();
321 scc.Sstruct.Sstructalign = 8;
322 //scc.Sstruct.ptrtype = TYM.TYnptr;
323 scc.Sstruct.Sflags = STR.STRglobal;
324
325 t = type_alloc(TYM.TYstruct);
326 t.Tflags |= TF.TFsizeunknown | TF.TFforward;
327 t.Ttag = scc; // structure tag name
328 assert(t.Tmangle == 0);
329 t.Tmangle = mTYman.mTYman_d;
330 t.Tcount++;
331 scc.Stype = t;
332 slist_add(scc);
333 return scc;
334 }
335
336 /******************************************
337 * Return elem that evaluates to the static frame pointer for function fd.
338 * If fd is a member function, the returned expression will compute the value
339 * of fd's 'this' variable.
340 * This routine is critical for implementing nested functions.
341 */
342
343 elem* getEthis(Loc loc, IRState* irs, Dsymbol fd)
344 {
345 elem* ethis;
346 FuncDeclaration thisfd = irs.getFunc();
347 Dsymbol fdparent = fd.toParent2();
348
349 //printf("getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", thisfd.toChars(), fd.toChars(), fdparent.toChars());
350 if (fdparent == thisfd)
351 {
352 /* Going down one nesting level, i.e. we're calling
353 * a nested function from its enclosing function.
354 */
355 ///version (DMDV2) {
356 if (irs.sclosure)
357 ethis = el_var(irs.sclosure);
358 else
359 ///}
360 if (irs.sthis)
361 {
362 // We have a 'this' pointer for the current function
363 ethis = el_var(irs.sthis);
364
365 /* If no variables in the current function's frame are
366 * referenced by nested functions, then we can 'skip'
367 * adding this frame into the linked list of stack
368 * frames.
369 */
370 version (DMDV2) {
371 bool cond = (thisfd.closureVars.dim != 0);
372 } else {
373 bool cond = thisfd.nestedFrameRef;
374 }
375 if (cond)
376 {
377 /* Local variables are referenced, can't skip.
378 * Address of 'this' gives the 'this' for the nested
379 * function
380 */
381 ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis);
382 }
383 }
384 else
385 {
386 /* No 'this' pointer for current function,
387 * use null if no references to the current function's frame
388 */
389 ethis = el_long(TYM.TYnptr, 0);
390 version (DMDV2) {
391 bool cond = (thisfd.closureVars.dim != 0);
392 } else {
393 bool cond = thisfd.nestedFrameRef;
394 }
395 if (cond)
396 {
397 /* OPframeptr is an operator that gets the frame pointer
398 * for the current function, i.e. for the x86 it gets
399 * the value of EBP
400 */
401 ethis.Eoper = OPER.OPframeptr;
402 }
403 }
404 }
405 else
406 {
407 if (!irs.sthis) // if no frame pointer for this function
408 {
409 fd.error(loc, "is a nested function and cannot be accessed from %s", irs.getFunc().toChars());
410 ethis = el_long(TYM.TYnptr, 0); // error recovery
411 }
412 else
413 {
414 ethis = el_var(irs.sthis);
415 Dsymbol s = thisfd;
416 while (fd != s)
417 {
418 /* Go up a nesting level, i.e. we need to find the 'this'
419 * of an enclosing function.
420 * Our 'enclosing function' may also be an inner class.
421 */
422
423 //printf("\ts = '%s'\n", s.toChars());
424 thisfd = s.isFuncDeclaration();
425 if (thisfd)
426 {
427 /* Enclosing function is a function.
428 */
429 if (fdparent == s.toParent2())
430 break;
431
432 if (thisfd.isNested())
433 {
434 FuncDeclaration p = s.toParent2().isFuncDeclaration();
435 version (DMDV2) {
436 bool cond = !p || p.closureVars.dim;
437 } else {
438 bool cond = !p || p.nestedFrameRef;
439 }
440 if (cond) {
441 ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
442 }
443 }
444 else if (thisfd.vthis)
445 {
446 ;
447 }
448 else
449 {
450 // Error should have been caught by front end
451 assert(0);
452 }
453 }
454 else
455 {
456 /* Enclosed by an aggregate. That means the current
457 * function must be a member function of that aggregate.
458 */
459 ClassDeclaration cd;
460 StructDeclaration sd;
461 AggregateDeclaration ad = s.isAggregateDeclaration();
462
463 if (!ad)
464 goto Lnoframe;
465
466 cd = s.isClassDeclaration();
467
468 if (cd && fd.isClassDeclaration() && fd.isClassDeclaration().isBaseOf(cd, null))
469 break;
470
471 sd = s.isStructDeclaration();
472
473 if (fd == sd)
474 break;
475
476 if (!ad.isNested() || !ad.vthis)
477 {
478 Lnoframe:
479 irs.getFunc().error(loc, "cannot get frame pointer to %s", fd.toChars());
480 return el_long(TYM.TYnptr, 0); // error recovery
481 }
482
483 ethis = el_bin(OPER.OPadd, TYM.TYnptr, ethis, el_long(TYM.TYint, ad.vthis.offset));
484 ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
485
486 if (fdparent == s.toParent2())
487 break;
488
489 if (auto fdd = s.toParent2().isFuncDeclaration())
490 {
491 /* Remember that frames for functions that have no
492 * nested references are skipped in the linked list
493 * of frames.
494 */
495 version (DMDV2) {
496 bool cond = (fdd.closureVars.dim != 0);
497 } else {
498 bool cond = fdd.nestedFrameRef;
499 }
500 if (cond) {
501 ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
502 }
503 break;
504 }
505 }
506 s = s.toParent2();
507 assert(s);
508 }
509 }
510 }
511
512 static if (false) {
513 printf("ethis:\n");
514 elem_print(ethis);
515 printf("\n");
516 }
517
518 return ethis;
519 }
520
521 /*****************************************
522 * Convert array to a pointer to the data.
523 */
524
525 elem* array_toPtr(Type t, elem* e)
526 {
527 //printf("array_toPtr()\n");
528 //elem_print(e);
529 t = t.toBasetype();
530 switch (t.ty)
531 {
532 case TY.Tpointer:
533 break;
534
535 case TY.Tarray:
536 case TY.Tdelegate:
537 if (e.Eoper == OPER.OPcomma)
538 {
539 e.Ety = TYM.TYnptr;
540 e.E2() = array_toPtr(t, e.E2);
541 }
542 else if (e.Eoper == OPER.OPpair)
543 {
544 e.Eoper = OPER.OPcomma;
545 e.Ety = TYM.TYnptr;
546 }
547 else
548 {
549 static if (true) {
550 e = el_una(OPER.OPmsw, TYM.TYnptr, e);
551 } else {
552 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
553 e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, 4));
554 e = el_una(OPER.OPind, TYM.TYnptr, e);
555 }
556 }
557 break;
558
559 case TY.Tsarray:
560 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
561 break;
562
563 default:
564 ///t.print();
565 assert(0);
566 }
567 return e;
568 }
569
570 /*******************************************
571 * Take address of an elem.
572 */
573
574 elem* addressElem(elem* e, Type t)
575 {
576 elem** pe;
577
578 //printf("addressElem()\n");
579
580 for (pe = &e; (*pe).Eoper == OPER.OPcomma; pe = &(*pe).E2()) {
581 ;
582 }
583
584 if ((*pe).Eoper != OPER.OPvar && (*pe).Eoper != OPER.OPind)
585 {
586 Symbol* stmp;
587 elem* eeq;
588 elem* ee = *pe;
589 type* tx;
590
591 // Convert to ((tmp=ee),tmp)
592 TY ty;
593 if (t && ((ty = t.toBasetype().ty) == TY.Tstruct || ty == TY.Tsarray))
594 tx = t.toCtype();
595 else
596 tx = type_fake(ee.Ety);
597 stmp = symbol_genauto(tx);
598 eeq = el_bin(OPER.OPeq,ee.Ety,el_var(stmp),ee);
599
600 if (tybasic(ee.Ety) == TYM.TYstruct)
601 {
602 eeq.Eoper = OPER.OPstreq;
603 eeq.Enumbytes = ee.Enumbytes;
604 }
605 else if (tybasic(ee.Ety) == TYM.TYarray)
606 {
607 eeq.Eoper = OPER.OPstreq;
608 eeq.Ety = TYM.TYstruct;
609 eeq.Ejty = cast(ubyte)eeq.Ety;
610 eeq.Enumbytes = cast(uint)t.size();
611 }
612 *pe = el_bin(OPER.OPcomma, ee.Ety, eeq, el_var(stmp));
613 }
614
615 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
616 return e;
617 }
618
619 /*******************************************
620 * Convert intrinsic function to operator.
621 * Returns that operator, -1 if not an intrinsic function.
622 */
623
624 extern (C++) extern int intrinsic_op(char* name);
625
626 OPER intrinsic_oper(const(char)* name)
627 {
628 int result = intrinsic_op(cast(char*)name);
629 if (result == -1) return OPER.OPMAX;
630 return cast(OPER)result;
631 }
632
633 /**************************************
634 */
635
636 elem* Dsymbol_toElem(Dsymbol s, IRState *irs)
637 {
638 elem *e = null;
639 Symbol* sp;
640 AttribDeclaration ad;
641 VarDeclaration vd;
642 ClassDeclaration cd;
643 StructDeclaration sd;
644 FuncDeclaration fd;
645 TemplateMixin tm;
646 TupleDeclaration td;
647 TypedefDeclaration tyd;
648
649 //printf("Dsymbol_toElem() %s\n", s.toChars());
650 ad = s.isAttribDeclaration();
651 if (ad)
652 {
653 Array decl = ad.include(null, null);
654 if (decl && decl.dim)
655 {
656 for (size_t i = 0; i < decl.dim; i++)
657 {
658 s = cast(Dsymbol)decl.data[i];
659 e = el_combine(e, Dsymbol_toElem(s, irs));
660 }
661 }
662 }
663 else if ((vd = s.isVarDeclaration()) !is null)
664 {
665 s = s.toAlias();
666 if (s != vd)
667 return Dsymbol_toElem(s, irs);
668 if (vd.isStatic() || vd.storage_class & (STC.STCextern | STC.STCtls | STC.STCgshared))
669 vd.toObjFile(0);
670 else
671 {
672 sp = s.toSymbol();
673 symbol_add(sp);
674 //printf("\tadding symbol '%s'\n", sp.Sident);
675 if (vd.init)
676 {
677 ExpInitializer ie = vd.init.isExpInitializer();
678 if (ie) {
679 e = ie.exp.toElem(irs);
680 }
681 }
682 }
683 }
684 else if ((cd = s.isClassDeclaration()) !is null)
685 {
686 irs.deferToObj.push(cast(void*)s);
687 }
688 else if ((sd = s.isStructDeclaration()) !is null)
689 {
690 irs.deferToObj.push(cast(void*)sd);
691 }
692 else if ((fd = s.isFuncDeclaration()) !is null)
693 {
694 //printf("function %s\n", fd.toChars());
695 irs.deferToObj.push(cast(void*)fd);
696 }
697 else if ((tm = s.isTemplateMixin()) !is null)
698 {
699 //printf("%s\n", tm.toChars());
700 if (tm.members)
701 {
702 for (size_t i = 0; i < tm.members.dim; i++)
703 {
704 Dsymbol sm = cast(Dsymbol)tm.members.data[i];
705 e = el_combine(e, Dsymbol_toElem(sm, irs));
706 }
707 }
708 }
709 else if ((td = s.isTupleDeclaration()) !is null)
710 {
711 for (size_t i = 0; i < td.objects.dim; i++)
712 {
713 Object o = cast(Object)td.objects.data[i];
714 ///if (o.dyncast() == DYNCAST_EXPRESSION)
715 if (Expression eo = cast(Expression)o)
716 {
717 if (eo.op == TOK.TOKdsymbol)
718 {
719 DsymbolExp se = cast(DsymbolExp)eo;
720 e = el_combine(e, Dsymbol_toElem(se.s, irs));
721 }
722 }
723 }
724 }
725 else if ((tyd = s.isTypedefDeclaration()) !is null)
726 {
727 irs.deferToObj.push(cast(void*)tyd);
728 }
729
730 return e;
731 }
732
733 /**************************************
734 * Given an expression e that is an array,
735 * determine and set the 'length' variable.
736 * Input:
737 * lengthVar Symbol of 'length' variable
738 * &e expression that is the array
739 * t1 Type of the array
740 * Output:
741 * e is rewritten to avoid side effects
742 * Returns:
743 * expression that initializes 'length'
744 */
745
746 elem* resolveLengthVar(VarDeclaration lengthVar, elem** pe, Type t1)
747 {
748 //printf("resolveLengthVar()\n");
749 elem* einit = null;
750
751 if (lengthVar && !(lengthVar.storage_class & STC.STCconst))
752 {
753 elem* elength;
754 Symbol* slength;
755
756 if (t1.ty == TY.Tsarray)
757 {
758 TypeSArray tsa = cast(TypeSArray)t1;
759 long length = tsa.dim.toInteger();
760
761 elength = el_long(TYM.TYuint, length);
762 goto L3;
763 }
764 else if (t1.ty == TY.Tarray)
765 {
766 elength = *pe;
767 *pe = el_same(&elength);
768 elength = el_una(OPER.OP64_32, TYM.TYuint, elength);
769
770 L3:
771 slength = lengthVar.toSymbol();
772 //symbol_add(slength);
773
774 einit = el_bin(OPER.OPeq, TYM.TYuint, el_var(slength), elength);
775 }
776 }
777 return einit;
778 }
779
780 /*******************************************
781 * Set an array pointed to by eptr to evalue:
782 * eptr[0..edim] = evalue;
783 * Input:
784 * eptr where to write the data to
785 * evalue value to write
786 * edim number of times to write evalue to eptr[]
787 * tb type of evalue
788 */
789
790 elem* setArray(elem* eptr, elem* edim, Type tb, elem* evalue, IRState* irs, int op)
791 {
792 int r;
793 elem* e;
794 int sz = cast(int)tb.size();
795
796 if (tb.ty == TY.Tfloat80 || tb.ty == TY.Timaginary80)
797 r = RTLSYM.RTLSYM_MEMSET80;
798 else if (tb.ty == TY.Tcomplex80)
799 r = RTLSYM.RTLSYM_MEMSET160;
800 else if (tb.ty == TY.Tcomplex64)
801 r = RTLSYM.RTLSYM_MEMSET128;
802 else
803 {
804 switch (sz)
805 {
806 case 1: r = RTLSYM.RTLSYM_MEMSET8; break;
807 case 2: r = RTLSYM.RTLSYM_MEMSET16; break;
808 case 4: r = RTLSYM.RTLSYM_MEMSET32; break;
809 case 8: r = RTLSYM.RTLSYM_MEMSET64; break;
810 default: r = RTLSYM.RTLSYM_MEMSETN; break;
811 }
812
813 /* Determine if we need to do postblit
814 */
815 if (op != TOK.TOKblit)
816 {
817 StructDeclaration sd = needsPostblit(tb);
818 if (sd)
819 {
820 /* Need to do postblit.
821 * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
822 */
823 r = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYSETCTOR : RTLSYM.RTLSYM_ARRAYSETASSIGN;
824 evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue);
825 Expression ti = tb.getTypeInfo(null);
826 elem* eti = ti.toElem(irs);
827 e = el_params(eti, edim, evalue, eptr, null);
828 e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
829 return e;
830 }
831 }
832
833 if (r == RTLSYM.RTLSYM_MEMSETN)
834 {
835 // void *_memsetn(void *p, void *value, int dim, int sizelem)
836 evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue);
837 elem *esz = el_long(TYM.TYint, sz);
838 e = el_params(esz, edim, evalue, eptr, null);
839 e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
840 return e;
841 }
842 }
843 if (sz > 1 && sz <= 8 && evalue.Eoper == OPER.OPconst && el_allbits(evalue, 0))
844 {
845 r = RTLSYM.RTLSYM_MEMSET8;
846 edim = el_bin(OPER.OPmul, TYM.TYuint, edim, el_long(TYM.TYuint, sz));
847 }
848
849 if (tybasic(evalue.Ety) == TYM.TYstruct)
850 {
851 evalue = el_una(OPER.OPstrpar, TYM.TYstruct, evalue);
852 evalue.Enumbytes = evalue.E1.Enumbytes;
853 assert(evalue.Enumbytes);
854 }
855
856 // Be careful about parameter side effect ordering
857 if (r == RTLSYM.RTLSYM_MEMSET8)
858 {
859 e = el_param(edim, evalue);
860 e = el_bin(OPER.OPmemset, TYM.TYnptr, eptr, e);
861 }
862 else
863 {
864 e = el_params(edim, evalue, eptr, null);
865 e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
866 }
867 return e;
868 }
869
870 /*************************
871 * Initialize the hidden aggregate member, vthis, with
872 * the context pointer.
873 * Returns:
874 * *(ey + ad.vthis.offset) = this;
875 */
876 version (DMDV2) {
877 elem* setEthis(Loc loc, IRState* irs, elem* ey, AggregateDeclaration ad)
878 {
879 elem* ethis;
880 FuncDeclaration thisfd = irs.getFunc();
881 int offset = 0;
882 Dsymbol cdp = ad.toParent2(); // class/func we're nested in
883
884 //printf("setEthis(ad = %s, cdp = %s, thisfd = %s)\n", ad.toChars(), cdp.toChars(), thisfd.toChars());
885
886 if (cdp is thisfd)
887 {
888 /* Class we're new'ing is a local class in this function:
889 * void thisfd() { class ad { } }
890 */
891 if (irs.sclosure)
892 ethis = el_var(irs.sclosure);
893 else if (irs.sthis)
894 {
895 /// version (DMDV2) {
896 if (thisfd.closureVars.dim)
897 /// } else {
898 /// if (thisfd.nestedFrameRef)
899 /// }
900 {
901 ethis = el_ptr(irs.sthis);
902 }
903 else
904 ethis = el_var(irs.sthis);
905 }
906 else
907 {
908 ethis = el_long(TYM.TYnptr, 0);
909 /// version (DMDV2) {
910 if (thisfd.closureVars.dim)
911 /// } else {
912 /// if (thisfd.nestedFrameRef)
913 /// }
914 {
915 ethis.Eoper = OPER.OPframeptr;
916 }
917 }
918 }
919 else if (thisfd.vthis && (
920 cdp == thisfd.toParent2() || (
921 cdp.isClassDeclaration() && cdp.isClassDeclaration().isBaseOf(thisfd.toParent2().isClassDeclaration(), &offset)
922 )
923 )
924 )
925 {
926 /* Class we're new'ing is at the same level as thisfd
927 */
928 assert(offset == 0); // BUG: should handle this case
929 ethis = el_var(irs.sthis);
930 }
931 else
932 {
933 ethis = getEthis(loc, irs, ad.toParent2());
934 ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis);
935 }
936
937 ey = el_bin(OPER.OPadd, TYM.TYnptr, ey, el_long(TYM.TYint, ad.vthis.offset));
938 ey = el_una(OPER.OPind, TYM.TYnptr, ey);
939 ey = el_bin(OPER.OPeq, TYM.TYnptr, ey, ethis);
940
941 return ey;
942 }
943 }
944
945 /********************************************
946 * Determine if t is an array of structs that need a postblit.
947 */
948 StructDeclaration needsPostblit(Type t)
949 {
950 t = t.toBasetype();
951
952 while (t.ty == TY.Tsarray)
953 t = t.nextOf().toBasetype();
954
955 if (t.ty == TY.Tstruct)
956 {
957 StructDeclaration sd = (cast(TypeStruct)t).sym;
958 if (sd.postblit)
959 return sd;
960 }
961
962 return null;
963 }
964
965 /*****************************************
966 * Convert array to a dynamic array.
967 */
968
969 elem* array_toDarray(Type t, elem* e)
970 {
971 uint dim;
972 elem* ef = null;
973 elem* ex;
974
975 //printf("array_toDarray(t = %s)\n", t.toChars());
976 //elem_print(e);
977 t = t.toBasetype();
978 switch (t.ty)
979 {
980 case TY.Tarray:
981 break;
982
983 case TY.Tsarray:
984 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
985 dim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
986 e = el_pair(TYM.TYullong, el_long(TYM.TYint, dim), e);
987 break;
988
989 default:
990 L1:
991 switch (e.Eoper)
992 {
993 case OPER.OPconst:
994 {
995 size_t len = tysize[tybasic(e.Ety)];
996 elem* es = el_calloc();
997 es.Eoper = OPER.OPstring;
998
999 // Match MEM_PH_FREE for OPstring in ztc\el.c
1000 es.EV.ss.Vstring = cast(char*)malloc(len); ///
1001 memcpy(es.EV.ss.Vstring, &e.EV, len);
1002
1003 es.EV.ss.Vstrlen = len;
1004 es.Ety = TYM.TYnptr;
1005 e = es;
1006 break;
1007 }
1008
1009 case OPER.OPvar:
1010 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
1011 break;
1012
1013 case OPER.OPcomma:
1014 ef = el_combine(ef, e.E1);
1015 ex = e;
1016 e = e.E2;
1017 ex.E1() = null;
1018 ex.E2() = null;
1019 el_free(ex);
1020 goto L1;
1021
1022 case OPER.OPind:
1023 ex = e;
1024 e = e.E1;
1025 ex.E1() = null;
1026 ex.E2() = null;
1027 el_free(ex);
1028 break;
1029
1030 default:
1031 {
1032 // Copy expression to a variable and take the
1033 // address of that variable.
1034 Symbol* stmp;
1035 tym_t ty = tybasic(e.Ety);
1036
1037 if (ty == TYM.TYstruct)
1038 {
1039 if (e.Enumbytes == 4)
1040 ty = TYM.TYint;
1041 else if (e.Enumbytes == 8)
1042 ty = TYM.TYllong;
1043 }
1044 e.Ety = ty;
1045 stmp = symbol_genauto(type_fake(ty));
1046 e = el_bin(OPER.OPeq, e.Ety, el_var(stmp), e);
1047 e = el_bin(OPER.OPcomma, TYM.TYnptr, e, el_una(OPER.OPaddr, TYM.TYnptr, el_var(stmp)));
1048 break;
1049 }
1050 }
1051 dim = 1;
1052 e = el_pair(TYM.TYullong, el_long(TYM.TYint, dim), e);
1053 break;
1054 }
1055
1056 return el_combine(ef, e);
1057 }
1058
1059 elem* sarray_toDarray(Loc loc, Type tfrom, Type tto, elem* e)
1060 {
1061 //printf("sarray_toDarray()\n");
1062 //elem_print(e);
1063
1064 elem* elen;
1065 uint dim = cast(uint)(cast(TypeSArray)tfrom).dim.toInteger();
1066
1067 if (tto)
1068 {
1069 uint fsize = cast(uint)tfrom.nextOf().size();
1070 uint tsize = cast(uint)tto.nextOf().size();
1071
1072 if ((dim * fsize) % tsize != 0)
1073 {
1074 Lerr:
1075 error(loc, "cannot cast %s to %s since sizes don't line up", tfrom.toChars(), tto.toChars());
1076 }
1077 dim = (dim * fsize) / tsize;
1078 }
1079
1080 L1:
1081 elen = el_long(TYM.TYint, dim);
1082 e = el_una(OPER.OPaddr, TYM.TYnptr, e);
1083 e = el_pair(TYM.TYullong, elen, e);
1084 return e;
1085 }
1086
1087 elem* eval_Darray(IRState* irs, Expression e)
1088 {
1089 elem* ex = e.toElem(irs);
1090 return array_toDarray(e.type, ex);
1091 }
1092
1093 /***********************************************
1094 * Generate code to set index into scope table.
1095 */
1096
1097 void setScopeIndex(Blockx* blx, block* b, int scope_index)
1098 {
1099 version (SEH) {
1100 block_appendexp(b, nteh_setScopeTableIndex(blx, scope_index));
1101 }
1102 }
1103
1104 /****************************************
1105 * Create a static symbol we can hang DT initializers onto.
1106 */
1107
1108 Symbol* static_sym()
1109 {
1110 Symbol* s;
1111 type* t;
1112
1113 t = type_alloc(TYint);
1114 t.Tcount++;
1115 s = symbol_calloc("internal");
1116 s.Sclass = SCstatic;
1117 s.Sfl = FLextern;
1118 s.Sflags |= SFLnodebug;
1119 s.Stype = t;
1120 version (ELFOBJ_OR_MACHOBJ) {
1121 s.Sseg = DATA;
1122 }
1123 slist_add(s);
1124 return s;
1125 }
1126
1127 /**************************************
1128 * Convert label to block.
1129 */
1130
1131 block* labelToBlock(Loc loc, Blockx *blx, LabelDsymbol label)
1132 {
1133 LabelStatement s;
1134
1135 if (!label.statement)
1136 {
1137 error(loc, "undefined label %s", label.toChars());
1138 return null;
1139 }
1140
1141 s = label.statement;
1142 if (!s.lblock)
1143 {
1144 s.lblock = block_calloc(blx);
1145 if (s.isReturnLabel)
1146 s.lblock.Btry = null;
1147 }
1148 return s.lblock;
1149 }