root/trunk/src/s2ir.c

Revision 730, 44.0 kB (checked in by walter, 2 years ago)

bugzilla 4398 dmd always uses Windows name mangling for _d_throw

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 2000-2010 by Digital Mars
3 // All Rights Reserved
4 // Written by Walter Bright
5 // http://www.digitalmars.com
6
7 #include        <stdio.h>
8 #include        <string.h>
9 #include        <time.h>
10
11 #include        "mars.h"
12 #include        "lexer.h"
13 #include        "statement.h"
14 #include        "expression.h"
15 #include        "mtype.h"
16 #include        "dsymbol.h"
17 #include        "declaration.h"
18 #include        "irstate.h"
19 #include        "init.h"
20 #include        "module.h"
21 #include        "enum.h"
22 #include        "aggregate.h"
23 #include        "template.h"
24 #include        "id.h"
25
26 // Back end
27 #include        "cc.h"
28 #include        "type.h"
29 #include        "code.h"
30 #include        "oper.h"
31 #include        "global.h"
32 #include        "dt.h"
33
34 #include        "rmem.h"
35
36 static char __file__[] = __FILE__;      // for tassert.h
37 #include        "tassert.h"
38
39 elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result);
40 elem *bit_read(elem *eb, elem *ei, int result);
41 elem *callfunc(Loc loc,
42         IRState *irs,
43         int directcall,         // 1: don't do virtual call
44         Type *tret,             // return type
45         elem *ec,               // evaluates to function address
46         Type *ectype,           // original type of ec
47         FuncDeclaration *fd,    // if !=NULL, this is the function being called
48         Type *t,                // TypeDelegate or TypeFunction for this function
49         elem *ehidden,          // if !=NULL, this is the 'hidden' argument
50         Array *arguments);
51
52 elem *exp2_copytotemp(elem *e);
53 elem *incUsageElem(IRState *irs, Loc loc);
54 StructDeclaration *needsPostblit(Type *t);
55
56 #define elem_setLoc(e,loc)      ((e)->Esrcpos.Sfilename = (char *)(loc).filename, \
57                                  (e)->Esrcpos.Slinnum = (loc).linnum)
58
59 #define SEH     (TARGET_WINDOS)
60
61 /***********************************************
62  * Generate code to set index into scope table.
63  */
64
65 #if SEH
66 void setScopeIndex(Blockx *blx, block *b, int scope_index)
67 {
68     block_appendexp(b, nteh_setScopeTableIndex(blx, scope_index));
69 }
70 #else
71 #define setScopeIndex(blx, b, scope_index) ;
72 #endif
73
74 /****************************************
75  * Allocate a new block, and set the tryblock.
76  */
77
78 block *block_calloc(Blockx *blx)
79 {
80     block *b = block_calloc();
81     b->Btry = blx->tryblock;
82     return b;
83 }
84
85 /**************************************
86  * Convert label to block.
87  */
88
89 block *labelToBlock(Loc loc, Blockx *blx, LabelDsymbol *label, int flag = 0)
90 {
91     if (!label->statement)
92     {
93         error(loc, "undefined label %s", label->toChars());
94         return NULL;
95     }
96     LabelStatement *s = label->statement;
97     if (!s->lblock)
98     {   s->lblock = block_calloc(blx);
99         s->lblock->Btry = NULL;         // fill this in later
100
101         if (flag)
102         {
103             // Keep track of the forward reference to this block, so we can check it later
104             if (!s->fwdrefs)
105                 s->fwdrefs = new Array();
106             s->fwdrefs->push(blx->curblock);
107         }
108     }
109     return s->lblock;
110 }
111
112 /**************************************
113  * Add in code to increment usage count for linnum.
114  */
115
116 void incUsage(IRState *irs, Loc loc)
117 {
118
119     if (global.params.cov && loc.linnum)
120     {
121         block_appendexp(irs->blx->curblock, incUsageElem(irs, loc));
122     }
123 }
124
125 /****************************************
126  * This should be overridden by each statement class.
127  */
128
129 void Statement::toIR(IRState *irs)
130 {
131     print();
132     assert(0);
133 }
134
135 /*************************************
136  */
137
138 void OnScopeStatement::toIR(IRState *irs)
139 {
140 }
141
142 /****************************************
143  */
144
145 void IfStatement::toIR(IRState *irs)
146 {
147     elem *e;
148     Blockx *blx = irs->blx;
149
150     //printf("IfStatement::toIR('%s')\n", condition->toChars());
151
152     IRState mystate(irs, this);
153
154     // bexit is the block that gets control after this IfStatement is done
155     block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();
156
157     incUsage(irs, loc);
158 #if 0
159     if (match)
160     {   /* Generate:
161          *  if (match = RTLSYM_IFMATCH(string, pattern)) ...
162          */
163         assert(condition->op == TOKmatch);
164         e = matchexp_toelem((MatchExp *)condition, &mystate, RTLSYM_IFMATCH);
165         Symbol *s = match->toSymbol();
166         symbol_add(s);
167         e = el_bin(OPeq, TYnptr, el_var(s), e);
168     }
169     else
170 #endif
171         e = condition->toElem(&mystate);
172     block_appendexp(blx->curblock, e);
173     block *bcond = blx->curblock;
174     block_next(blx, BCiftrue, NULL);
175
176     list_append(&bcond->Bsucc, blx->curblock);
177     if (ifbody)
178         ifbody->toIR(&mystate);
179     list_append(&blx->curblock->Bsucc, bexit);
180
181     if (elsebody)
182     {
183         block_next(blx, BCgoto, NULL);
184         list_append(&bcond->Bsucc, blx->curblock);
185         elsebody->toIR(&mystate);
186         list_append(&blx->curblock->Bsucc, bexit);
187     }
188     else
189         list_append(&bcond->Bsucc, bexit);
190
191     block_next(blx, BCgoto, bexit);
192
193 }
194
195 /**************************************
196  */
197
198 #if DMDV2
199 void PragmaStatement::toIR(IRState *irs)
200 {
201     //printf("PragmaStatement::toIR()\n");
202     if (ident == Id::startaddress)
203     {
204         assert(args && args->dim == 1);
205         Expression *e = (Expression *)args->data[0];
206         Dsymbol *sa = getDsymbol(e);
207         FuncDeclaration *f = sa->isFuncDeclaration();
208         assert(f);
209         Symbol *s = f->toSymbol();
210         while (irs->prev)
211             irs = irs->prev;
212         irs->startaddress = s;
213     }
214 }
215 #endif
216
217 /***********************
218  */
219
220 void WhileStatement::toIR(IRState *irs)
221 {
222     assert(0); // was "lowered"
223 #if 0
224     Blockx *blx = irs->blx;
225
226     /* Create a new state, because we need a new continue and break target
227      */
228     IRState mystate(irs,this);
229     mystate.breakBlock = block_calloc(blx);
230     mystate.contBlock = block_calloc(blx);
231
232     list_append(&blx->curblock->Bsucc, mystate.contBlock);
233     block_next(blx, BCgoto, mystate.contBlock);
234     incUsage(irs, loc);
235     block_appendexp(mystate.contBlock, condition->toElem(&mystate));
236
237     block_next(blx, BCiftrue, NULL);
238
239     /* curblock is the start of the while loop body
240      */
241     list_append(&mystate.contBlock->Bsucc, blx->curblock);
242     if (body)
243         body->toIR(&mystate);
244     list_append(&blx->curblock->Bsucc, mystate.contBlock);
245     block_next(blx, BCgoto, mystate.breakBlock);
246
247     list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
248 #endif
249 }
250
251 /******************************************
252  */
253
254 void DoStatement::toIR(IRState *irs)
255 {
256     Blockx *blx = irs->blx;
257
258     IRState mystate(irs,this);
259     mystate.breakBlock = block_calloc(blx);
260     mystate.contBlock = block_calloc(blx);
261
262     block *bpre = blx->curblock;
263     block_next(blx, BCgoto, NULL);
264     list_append(&bpre->Bsucc, blx->curblock);
265
266     list_append(&mystate.contBlock->Bsucc, blx->curblock);
267     list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
268
269     if (body)
270         body->toIR(&mystate);
271     list_append(&blx->curblock->Bsucc, mystate.contBlock);
272
273     block_next(blx, BCgoto, mystate.contBlock);
274     incUsage(irs, condition->loc);
275     block_appendexp(mystate.contBlock, condition->toElem(&mystate));
276     block_next(blx, BCiftrue, mystate.breakBlock);
277
278 }
279
280 /*****************************************
281  */
282
283 void ForStatement::toIR(IRState *irs)
284 {
285     Blockx *blx = irs->blx;
286
287     IRState mystate(irs,this);
288     mystate.breakBlock = block_calloc(blx);
289     mystate.contBlock = block_calloc(blx);
290
291     if (init)
292         init->toIR(&mystate);
293     block *bpre = blx->curblock;
294     block_next(blx,BCgoto,NULL);
295     block *bcond = blx->curblock;
296     list_append(&bpre->Bsucc, bcond);
297     list_append(&mystate.contBlock->Bsucc, bcond);
298     if (condition)
299     {
300         incUsage(irs, condition->loc);
301         block_appendexp(bcond, condition->toElem(&mystate));
302         block_next(blx,BCiftrue,NULL);
303         list_append(&bcond->Bsucc, blx->curblock);
304         list_append(&bcond->Bsucc, mystate.breakBlock);
305     }
306     else
307     {   /* No conditional, it's a straight goto
308          */
309         block_next(blx,BCgoto,NULL);
310         list_append(&bcond->Bsucc, blx->curblock);
311     }
312
313     if (body)
314         body->toIR(&mystate);
315     /* End of the body goes to the continue block
316      */
317     list_append(&blx->curblock->Bsucc, mystate.contBlock);
318     block_next(blx, BCgoto, mystate.contBlock);
319
320     if (increment)
321     {
322         incUsage(irs, increment->loc);
323         block_appendexp(mystate.contBlock, increment->toElem(&mystate));
324     }
325
326     /* The 'break' block follows the for statement.
327      */
328     block_next(blx,BCgoto, mystate.breakBlock);
329 }
330
331
332 /**************************************
333  */
334
335 void ForeachStatement::toIR(IRState *irs)
336 {
337     assert(0);  // done by "lowering" in the front end
338 #if 0
339     Type *tab;
340     elem *eaggr;
341     elem *e;
342     elem *elength;
343     tym_t keytym;
344
345     //printf("ForeachStatement::toIR()\n");
346     block *bpre;
347     block *bcond;
348     block *bbody;
349     block *bbodyx;
350     Blockx *blx = irs->blx;
351
352     IRState mystate(irs,this);
353     mystate.breakBlock = block_calloc(blx);
354     mystate.contBlock = block_calloc(blx);
355
356     tab = aggr->type->toBasetype();
357     assert(tab->ty == Tarray || tab->ty == Tsarray);
358
359     incUsage(irs, aggr->loc);
360     eaggr = aggr->toElem(irs);
361
362     /* Create sp: pointer to start of array data
363      */
364
365     Symbol *sp = symbol_genauto(TYnptr);
366
367     if (tab->ty == Tarray)
368     {
369         // stmp is copy of eaggr (the array), so eaggr is evaluated only once
370         Symbol *stmp;
371
372         // Initialize stmp
373         stmp = symbol_genauto(eaggr);
374         e = el_bin(OPeq, eaggr->Ety, el_var(stmp), eaggr);
375         block_appendexp(blx->curblock, e);
376
377         // Initialize sp
378         e = el_una(OPmsw, TYnptr, el_var(stmp));
379         e = el_bin(OPeq, TYnptr, el_var(sp), e);
380         block_appendexp(blx->curblock, e);
381
382         // Get array.length
383         elength = el_var(stmp);
384         elength->Ety = TYsize_t;
385     }
386     else // Tsarray
387     {
388         // Initialize sp
389         e = el_una(OPaddr, TYnptr, eaggr);
390         e = el_bin(OPeq, TYnptr, el_var(sp), e);
391         block_appendexp(blx->curblock, e);
392
393         // Get array.length
394         elength = el_long(TYsize_t, ((TypeSArray *)tab)->dim->toInteger());
395     }
396
397     Symbol *spmax;
398     Symbol *skey;
399
400     if (key)
401     {
402         /* Create skey, the index to the array.
403          * Initialize skey to 0 (foreach) or .length (foreach_reverse).
404          */
405         skey = key->toSymbol();
406         symbol_add(skey);
407         keytym = key->type->totym();
408         elem *einit = (op == TOKforeach_reverse) ? elength : el_long(keytym, 0);
409         e = el_bin(OPeq, keytym, el_var(skey), einit);
410     }
411     else
412     {
413         /* Create spmax, pointer past end of data.
414          * Initialize spmax = sp + array.length * size
415          */
416         spmax = symbol_genauto(TYnptr);
417         e = el_bin(OPmul, TYsize_t, elength, el_long(TYsize_t, tab->nextOf()->size()));
418         e = el_bin(OPadd, TYnptr, el_var(sp), e);
419         e = el_bin(OPeq, TYnptr, el_var(spmax), e);
420
421         /* For foreach_reverse, swap sp and spmax
422          */
423         if (op == TOKforeach_reverse)
424         {   Symbol *s = sp;
425             sp = spmax;
426             spmax = s;
427         }
428     }
429     block_appendexp(blx->curblock, e);
430
431     bpre = blx->curblock;
432     block_next(blx,BCgoto,NULL);
433     bcond = blx->curblock;
434
435     if (key)
436     {
437         if (op == TOKforeach_reverse)
438         {
439             // Construct (key != 0)
440             e = el_bin(OPne, TYint, el_var(skey), el_long(keytym, 0));
441         }
442         else
443         {
444             // Construct (key < elength)
445             e = el_bin(OPlt, TYint, el_var(skey), elength);
446         }
447     }
448     else
449     {
450         if (op == TOKforeach_reverse)
451         {
452             // Construct (sp > spmax)
453             e = el_bin(OPgt, TYint, el_var(sp), el_var(spmax));
454         }
455         else
456         {
457             // Construct (sp < spmax)
458             e = el_bin(OPlt, TYint, el_var(sp), el_var(spmax));
459         }
460     }
461     bcond->Belem = e;
462     block_next(blx, BCiftrue, NULL);
463
464     if (op == TOKforeach_reverse)
465     {
466         if (key)
467         {   // Construct (skey -= 1)
468             e = el_bin(OPminass, keytym, el_var(skey), el_long(keytym, 1));
469         }
470         else
471         {   // Construct (sp--)
472             e = el_bin(OPminass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
473         }
474         block_appendexp(blx->curblock, e);
475     }
476
477     Symbol *s;
478     FuncDeclaration *fd = NULL;
479     if (value->toParent2())
480         fd = value->toParent2()->isFuncDeclaration();
481     int nrvo = 0;
482     if (fd && fd->nrvo_can && fd->nrvo_var == value)
483     {
484         s = fd->shidden;
485         nrvo = 1;
486     }
487     else
488     {   s = value->toSymbol();
489         symbol_add(s);
490     }
491
492     // Construct (value = *sp) or (value = sp[skey * elemsize])
493     tym_t tym = value->type->totym();
494     if (key)
495     {   // sp + skey * elemsize
496         e = el_bin(OPmul, keytym, el_var(skey), el_long(keytym, tab->nextOf()->size()));
497         e = el_bin(OPadd, TYnptr, el_var(sp), e);
498     }
499     else
500         e = el_var(sp);
501
502     elem *evalue;
503 #if DMDV2
504     if (value->offset)  // if value is a member of a closure
505     {
506         assert(irs->sclosure);
507         evalue = el_var(irs->sclosure);
508         evalue = el_bin(OPadd, TYnptr, evalue, el_long(TYint, value->offset));
509         evalue = el_una(OPind, value->type->totym(), evalue);
510     }
511     else
512 #endif
513         evalue = el_var(s);
514
515     if (value->isOut() || value->isRef())
516     {
517         assert(value->storage_class & (STCout | STCref));
518         e = el_bin(OPeq, TYnptr, evalue, e);
519     }
520     else
521     {
522         if (nrvo)
523             evalue = el_una(OPind, tym, evalue);
524         StructDeclaration *sd = needsPostblit(value->type);
525         if (tybasic(tym) == TYstruct)
526         {
527             e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
528             e->Eoper = OPstreq;
529             e->ET = value->type->toCtype();
530 #if DMDV2
531             // Call postblit on e
532             if (sd)
533             {   FuncDeclaration *fd = sd->postblit;
534                 elem *ec = el_copytree(evalue);
535                 ec = el_una(OPaddr, TYnptr, ec);
536                 ec = callfunc(loc, irs, 1, Type::tvoid, ec, sd->type->pointerTo(), fd, fd->type, NULL, NULL);
537                 e = el_combine(e, ec);
538             }
539 #endif
540         }
541         else if (tybasic(tym) == TYarray)
542         {
543             if (sd)
544             {
545                 /* Generate:
546                  *      _d_arrayctor(ti, efrom, eto)
547                  */
548                 Expression *ti = value->type->toBasetype()->nextOf()->toBasetype()->getTypeInfo(NULL);
549                 elem *esize = el_long(TYsize_t, ((TypeSArray *)value->type->toBasetype())->dim->toInteger());
550                 elem *eto = el_pair(TYdarray, esize, el_una(OPaddr, TYnptr, evalue));
551                 elem *efrom = el_pair(TYdarray, el_copytree(esize), e);
552                 elem *ep = el_params(eto, efrom, ti->toElem(irs), NULL);
553                 int rtl = RTLSYM_ARRAYCTOR;
554                 e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), ep);
555             }
556             else
557             {
558                 e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
559                 e->Eoper = OPstreq;
560                 e->Ejty = e->Ety = TYstruct;
561                 e->ET = value->type->toCtype();
562             }
563         }
564         else
565             e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
566     }
567     incUsage(irs, loc);
568     block_appendexp(blx->curblock, e);
569
570     bbody = blx->curblock;
571     if (body)
572         body->toIR(&mystate);
573     bbodyx = blx->curblock;
574     block_next(blx,BCgoto,mystate.contBlock);
575
576     if (op == TOKforeach)
577     {
578         if (key)
579         {   // Construct (skey += 1)
580             e = el_bin(OPaddass, keytym, el_var(skey), el_long(keytym, 1));
581         }
582         else
583         {   // Construct (sp++)
584             e = el_bin(OPaddass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
585         }
586         mystate.contBlock->Belem = e;
587     }
588     block_next(blx,BCgoto,mystate.breakBlock);
589
590     list_append(&bpre->Bsucc,bcond);
591     list_append(&bcond->Bsucc,bbody);
592     list_append(&bcond->Bsucc,mystate.breakBlock);
593     list_append(&bbodyx->Bsucc,mystate.contBlock);
594     list_append(&mystate.contBlock->Bsucc,bcond);
595 #endif
596 }
597
598
599 /**************************************
600  */
601
602 #if DMDV2
603 void ForeachRangeStatement::toIR(IRState *irs)
604 {
605     assert(0);
606 #if 0
607     Type *tab;
608     elem *eaggr;
609     elem *elwr;
610     elem *eupr;
611     elem *e;
612     elem *elength;
613     tym_t keytym;
614
615     //printf("ForeachStatement::toIR()\n");
616     block *bpre;
617     block *bcond;
618     block *bbody;
619     block *bbodyx;
620     Blockx *blx = irs->blx;
621
622     IRState mystate(irs,this);
623     mystate.breakBlock = block_calloc(blx);
624     mystate.contBlock = block_calloc(blx);
625
626     incUsage(irs, lwr->loc);
627     elwr = lwr->toElem(irs);
628
629     incUsage(irs, upr->loc);
630     eupr = upr->toElem(irs);
631
632     /* Create skey, the index to the array.
633      * Initialize skey to elwr (foreach) or eupr (foreach_reverse).
634      */
635     Symbol *skey = key->toSymbol();
636     symbol_add(skey);
637     keytym = key->type->totym();
638
639     elem *ekey;
640     if (key->offset)            // if key is member of a closure
641     {
642         assert(irs->sclosure);
643         ekey = el_var(irs->sclosure);
644         ekey = el_bin(OPadd, TYnptr, ekey, el_long(TYint, key->offset));
645         ekey = el_una(OPind, keytym, ekey);
646     }
647     else
648         ekey = el_var(skey);
649
650     elem *einit = (op == TOKforeach_reverse) ? eupr : elwr;
651     e = el_bin(OPeq, keytym, ekey, einit);   // skey = einit;
652     block_appendexp(blx->curblock, e);
653
654     /* Make a copy of the end condition, so it only
655      * gets evaluated once.
656      */
657     elem *eend = (op == TOKforeach_reverse) ? elwr : eupr;
658     Symbol *send = symbol_genauto(eend);
659     e = el_bin(OPeq, eend->Ety, el_var(send), eend);
660     assert(tybasic(e->Ety) != TYstruct);
661     block_appendexp(blx->curblock, e);
662
663     bpre = blx->curblock;
664     block_next(blx,BCgoto,NULL);
665     bcond = blx->curblock;
666
667     if (op == TOKforeach_reverse)
668     {
669         // Construct (key > elwr)
670         e = el_bin(OPgt, TYint, el_copytree(ekey), el_var(send));
671     }
672     else
673     {
674         // Construct (key < eupr)
675         e = el_bin(OPlt, TYint, el_copytree(ekey), el_var(send));
676     }
677
678     // The size of the increment
679     size_t sz = 1;
680     Type *tkeyb = key->type->toBasetype();
681     if (tkeyb->ty == Tpointer)
682         sz = tkeyb->nextOf()->size();
683
684     bcond->Belem = e;
685     block_next(blx, BCiftrue, NULL);
686
687     if (op == TOKforeach_reverse)
688     {
689         // Construct (skey -= 1)
690         e = el_bin(OPminass, keytym, el_copytree(ekey), el_long(keytym, sz));
691         block_appendexp(blx->curblock, e);
692     }
693
694     bbody = blx->curblock;
695     if (body)
696         body->toIR(&mystate);
697     bbodyx = blx->curblock;
698     block_next(blx,BCgoto,mystate.contBlock);
699
700     if (op == TOKforeach)
701     {
702         // Construct (skey += 1)
703         e = el_bin(OPaddass, keytym, el_copytree(ekey), el_long(keytym, sz));
704         mystate.contBlock->Belem = e;
705     }
706     block_next(blx,BCgoto,mystate.breakBlock);
707
708     list_append(&bpre->Bsucc,bcond);
709     list_append(&bcond->Bsucc,bbody);
710     list_append(&bcond->Bsucc,mystate.breakBlock);
711     list_append(&bbodyx->Bsucc,mystate.contBlock);
712     list_append(&mystate.contBlock->Bsucc,bcond);
713 #endif
714 }
715 #endif
716
717
718 /****************************************
719  */
720
721 void BreakStatement::toIR(IRState *irs)
722 {
723     block *bbreak;
724     block *b;
725     Blockx *blx = irs->blx;
726
727     bbreak = irs->getBreakBlock(ident);
728     assert(bbreak);
729     b = blx->curblock;
730     incUsage(irs, loc);
731
732     // Adjust exception handler scope index if in different try blocks
733     if (b->Btry != bbreak->Btry)
734     {
735         //setScopeIndex(blx, b, bbreak->Btry ? bbreak->Btry->Bscope_index : -1);
736     }
737
738     /* Nothing more than a 'goto' to the current break destination
739      */
740     list_append(&b->Bsucc, bbreak);
741     block_next(blx, BCgoto, NULL);
742 }
743
744 /************************************
745  */
746
747 void ContinueStatement::toIR(IRState *irs)
748 {
749     block *bcont;
750     block *b;
751     Blockx *blx = irs->blx;
752
753     //printf("ContinueStatement::toIR() %p\n", this);
754     bcont = irs->getContBlock(ident);
755     assert(bcont);
756     b = blx->curblock;
757     incUsage(irs, loc);
758
759     // Adjust exception handler scope index if in different try blocks
760     if (b->Btry != bcont->Btry)
761     {
762         //setScopeIndex(blx, b, bcont->Btry ? bcont->Btry->Bscope_index : -1);
763     }
764
765     /* Nothing more than a 'goto' to the current continue destination
766      */
767     list_append(&b->Bsucc, bcont);
768     block_next(blx, BCgoto, NULL);
769 }
770
771 /**************************************
772  */
773
774 void el_setVolatile(elem *e)
775 {
776     elem_debug(e);
777     while (1)
778     {
779         e->Ety |= mTYvolatile;
780         if (OTunary(e->Eoper))
781             e = e->E1;
782         else if (OTbinary(e->Eoper))
783         {   el_setVolatile(e->E2);
784             e = e->E1;
785         }
786         else
787             break;
788     }
789 }
790
791 void VolatileStatement::toIR(IRState *irs)
792 {
793     block *b;
794
795     if (statement)
796     {
797         Blockx *blx = irs->blx;
798
799         block_goto(blx, BCgoto, NULL);
800         b = blx->curblock;
801
802         statement->toIR(irs);
803
804         block_goto(blx, BCgoto, NULL);
805
806         // Mark the blocks generated as volatile
807         for (; b != blx->curblock; b = b->Bnext)
808         {   b->Bflags |= BFLvolatile;
809             if (b->Belem)
810                 el_setVolatile(b->Belem);
811         }
812     }
813 }
814
815 /**************************************
816  */
817
818 void GotoStatement::toIR(IRState *irs)
819 {
820     Blockx *blx = irs->blx;
821
822     if (!label->statement)
823     {   error("label %s is undefined", label->toChars());
824         return;
825     }
826     if (tf != label->statement->tf)
827         error("cannot goto forward out of or into finally block");
828
829     block *bdest = labelToBlock(loc, blx, label, 1);
830     if (!bdest)
831         return;
832     block *b = blx->curblock;
833     incUsage(irs, loc);
834
835     if (b->Btry != bdest->Btry)
836     {
837         // Check that bdest is in an enclosing try block
838         for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry)
839         {
840             if (!bt)
841             {
842                 //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry);
843                 error("cannot goto into try block");
844                 break;
845             }
846         }
847     }
848
849     list_append(&b->Bsucc,bdest);
850     block_next(blx,BCgoto,NULL);
851 }
852
853 void LabelStatement::toIR(IRState *irs)
854 {
855     //printf("LabelStatement::toIR() %p, statement = %p\n", this, statement);
856     Blockx *blx = irs->blx;
857     block *bc = blx->curblock;
858     IRState mystate(irs,this);
859     mystate.ident = ident;
860
861     if (lblock)
862     {
863         // At last, we know which try block this label is inside
864         lblock->Btry = blx->tryblock;
865
866         /* Go through the forward references and check.
867          */
868         if (fwdrefs)
869         {
870             for (int i = 0; i < fwdrefs->dim; i++)
871             {   block *b = (block *)fwdrefs->data[i];
872
873                 if (b->Btry != lblock->Btry)
874                 {
875                     // Check that lblock is in an enclosing try block
876                     for (block *bt = b->Btry; bt != lblock->Btry; bt = bt->Btry)
877                     {
878                         if (!bt)
879                         {
880                             //printf("b->Btry = %p, lblock->Btry = %p\n", b->Btry, lblock->Btry);
881                             error("cannot goto into try block");
882                             break;
883                         }
884                     }
885                 }
886
887             }
888             delete fwdrefs;
889             fwdrefs = NULL;
890         }
891     }
892     else
893         lblock = block_calloc(blx);
894     block_next(blx,BCgoto,lblock);
895     list_append(&bc->Bsucc,blx->curblock);
896     if (statement)
897         statement->toIR(&mystate);
898 }
899
900 /**************************************
901  */
902
903 void SwitchStatement::toIR(IRState *irs)
904 {
905     int string;
906     Blockx *blx = irs->blx;
907
908     //printf("SwitchStatement::toIR()\n");
909     IRState mystate(irs,this);
910
911     mystate.switchBlock = blx->curblock;
912
913     /* Block for where "break" goes to
914      */
915     mystate.breakBlock = block_calloc(blx);
916
917     /* Block for where "default" goes to.
918      * If there is a default statement, then that is where default goes.
919      * If not, then do:
920      *   default: break;
921      * by making the default block the same as the break block.
922      */
923     mystate.defaultBlock = sdefault ? block_calloc(blx) : mystate.breakBlock;
924
925     int numcases = 0;
926     if (cases)
927         numcases = cases->dim;
928
929     incUsage(irs, loc);
930     elem *econd = condition->toElem(&mystate);
931 #if DMDV2
932     if (hasVars)
933     {   /* Generate a sequence of if-then-else blocks for the cases.
934          */
935         if (econd->Eoper != OPvar)
936         {
937             elem *e = exp2_copytotemp(econd);
938             block_appendexp(mystate.switchBlock, e);
939             econd = e->E2;
940         }
941
942         for (int i = 0; i < numcases; i++)
943         {   CaseStatement *cs = (CaseStatement *)cases->data[i];
944
945             elem *ecase = cs->exp->toElem(&mystate);
946             elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase);
947             block *b = blx->curblock;
948             block_appendexp(b, e);
949             block *bcase = block_calloc(blx);
950             cs->cblock = bcase;
951             block_next(blx, BCiftrue, NULL);
952             list_append(&b->Bsucc, bcase);
953             list_append(&b->Bsucc, blx->curblock);
954         }
955
956         /* The final 'else' clause goes to the default
957          */
958         block *b = blx->curblock;
959         block_next(blx, BCgoto, NULL);
960         list_append(&b->Bsucc, mystate.defaultBlock);
961
962         body->toIR(&mystate);
963
964         /* Have the end of the switch body fall through to the block
965          * following the switch statement.
966          */
967         block_goto(blx, BCgoto, mystate.breakBlock);
968         return;
969     }
970 #endif
971
972     if (condition->type->isString())
973     {
974         // Number the cases so we can unscramble things after the sort()
975         for (int i = 0; i < numcases; i++)
976         {   CaseStatement *cs = (CaseStatement *)cases->data[i];
977             cs->index = i;
978         }
979
980         cases->sort();
981
982         /* Create a sorted array of the case strings, and si
983          * will be the symbol for it.
984          */
985         dt_t *dt = NULL;
986         Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray));
987 #if MACHOBJ
988         si->Sseg = DATA;
989 #endif
990         dtsize_t(&dt, numcases);
991         dtxoff(&dt, si, PTRSIZE * 2, TYnptr);
992
993         for (int i = 0; i < numcases; i++)
994         {   CaseStatement *cs = (CaseStatement *)cases->data[i];
995
996             if (cs->exp->op != TOKstring)
997             {   error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert
998             }
999             else
1000             {
1001                 StringExp *se = (StringExp *)(cs->exp);
1002                 unsigned len = se->len;
1003                 dtsize_t(&dt, len);
1004                 dtabytes(&dt, TYnptr, 0, se->len * se->sz, (char *)se->string);
1005             }
1006         }
1007
1008         si->Sdt = dt;
1009         si->Sfl = FLdata;
1010         outdata(si);
1011
1012         /* Call:
1013          *      _d_switch_string(string[] si, string econd)
1014          */
1015         elem *eparam = el_param(econd, el_var(si));
1016         switch (condition->type->nextOf()->ty)
1017         {
1018             case Tchar:
1019                 econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_STRING]), eparam);
1020                 break;
1021             case Twchar:
1022                 econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_USTRING]), eparam);
1023                 break;
1024             case Tdchar:        // BUG: implement
1025                 econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_DSTRING]), eparam);
1026                 break;
1027             default:
1028                 assert(0);
1029         }
1030         elem_setLoc(econd, loc);
1031         string = 1;
1032     }
1033     else
1034         string = 0;
1035     block_appendexp(mystate.switchBlock, econd);
1036     block_next(blx,BCswitch,NULL);
1037
1038     // Corresponding free is in block_free
1039     targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1));
1040     mystate.switchBlock->BS.Bswitch = pu;
1041     /* First pair is the number of cases, and the default block
1042      */
1043     *pu++ = numcases;
1044     list_append(&mystate.switchBlock->Bsucc, mystate.defaultBlock);
1045
1046     /* Fill in the first entry in each pair, which is the case value.
1047      * CaseStatement::toIR() will fill in
1048      * the second entry for each pair with the block.
1049      */
1050     for (int i = 0; i < numcases; i++)
1051     {
1052         CaseStatement *cs = (CaseStatement *)cases->data[i];
1053         if (string)
1054         {
1055             pu[cs->index] = i;
1056         }
1057         else
1058         {
1059             pu[i] = cs->exp->toInteger();
1060         }
1061     }
1062
1063     body->toIR(&mystate);
1064
1065     /* Have the end of the switch body fall through to the block
1066      * following the switch statement.
1067      */
1068     block_goto(blx, BCgoto, mystate.breakBlock);
1069 }
1070
1071 void CaseStatement::toIR(IRState *irs)
1072 {
1073     Blockx *blx = irs->blx;
1074     block *bcase = blx->curblock;
1075     if (!cblock)
1076         cblock = block_calloc(blx);
1077     block_next(blx,BCgoto,cblock);
1078     block *bsw = irs->getSwitchBlock();
1079     if (bsw->BC == BCswitch)
1080         list_append(&bsw->Bsucc,cblock);        // second entry in pair
1081     list_append(&bcase->Bsucc,cblock);
1082     if (blx->tryblock != bsw->Btry)
1083         error("case cannot be in different try block level from switch");
1084     incUsage(irs, loc);
1085     if (statement)
1086         statement->toIR(irs);
1087 }
1088
1089 void DefaultStatement::toIR(IRState *irs)
1090 {
1091     Blockx *blx = irs->blx;
1092     block *bcase = blx->curblock;
1093     block *bdefault = irs->getDefaultBlock();
1094     block_next(blx,BCgoto,bdefault);
1095     list_append(&bcase->Bsucc,blx->curblock);
1096     if (blx->tryblock != irs->getSwitchBlock()->Btry)
1097         error("default cannot be in different try block level from switch");
1098     incUsage(irs, loc);
1099     if (statement)
1100         statement->toIR(irs);
1101 }
1102
1103 void GotoDefaultStatement::toIR(IRState *irs)
1104 {
1105     block *b;
1106     Blockx *blx = irs->blx;
1107     block *bdest = irs->getDefaultBlock();
1108
1109     b = blx->curblock;
1110
1111     // The rest is equivalent to GotoStatement
1112
1113     // Adjust exception handler scope index if in different try blocks
1114     if (b->Btry != bdest->Btry)
1115     {
1116         // Check that bdest is in an enclosing try block
1117         for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry)
1118         {
1119             if (!bt)
1120             {
1121                 //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry);
1122                 error("cannot goto into try block");
1123                 break;
1124             }
1125         }
1126
1127         //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1);
1128     }
1129
1130     list_append(&b->Bsucc,bdest);
1131     incUsage(irs, loc);
1132     block_next(blx,BCgoto,NULL);
1133 }
1134
1135 void GotoCaseStatement::toIR(IRState *irs)
1136 {
1137     block *b;
1138     Blockx *blx = irs->blx;
1139     block *bdest = cs->cblock;
1140
1141     if (!bdest)
1142     {
1143         bdest = block_calloc(blx);
1144         cs->cblock = bdest;
1145     }
1146
1147     b = blx->curblock;
1148
1149     // The rest is equivalent to GotoStatement
1150
1151     // Adjust exception handler scope index if in different try blocks
1152     if (b->Btry != bdest->Btry)
1153     {
1154         // Check that bdest is in an enclosing try block
1155         for (block *bt = b->Btry; bt != bdest->Btry; bt = bt->Btry)
1156         {
1157             if (!bt)
1158             {
1159                 //printf("b->Btry = %p, bdest->Btry = %p\n", b->Btry, bdest->Btry);
1160                 error("cannot goto into try block");
1161                 break;
1162             }
1163         }
1164
1165         //setScopeIndex(blx, b, bdest->Btry ? bdest->Btry->Bscope_index : -1);
1166     }
1167
1168     list_append(&b->Bsucc,bdest);
1169     incUsage(irs, loc);
1170     block_next(blx,BCgoto,NULL);
1171 }
1172
1173 void SwitchErrorStatement::toIR(IRState *irs)
1174 {
1175     Blockx *blx = irs->blx;
1176
1177     //printf("SwitchErrorStatement::toIR()\n");
1178
1179     elem *efilename = el_ptr(blx->module->toSymbol());
1180     elem *elinnum = el_long(TYint, loc.linnum);
1181     elem *e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DSWITCHERR]), el_param(elinnum, efilename));
1182     block_appendexp(blx->curblock, e);
1183 }
1184
1185 /**************************************
1186  */
1187
1188 void ReturnStatement::toIR(IRState *irs)
1189 {
1190     Blockx *blx = irs->blx;
1191
1192     incUsage(irs, loc);
1193     if (exp)
1194     {   elem *e;
1195
1196         FuncDeclaration *func = irs->getFunc();
1197         assert(func);
1198         assert(func->type->ty == Tfunction);
1199         TypeFunction *tf = (TypeFunction *)(func->type);
1200
1201         enum RET retmethod = tf->retStyle();
1202         if (retmethod == RETstack)
1203         {
1204             elem *es;
1205
1206             /* If returning struct literal, write result
1207              * directly into return value
1208              */
1209             if (exp->op == TOKstructliteral)
1210             {   StructLiteralExp *se = (StructLiteralExp *)exp;
1211                 char save[sizeof(StructLiteralExp)];
1212                 memcpy(save, se, sizeof(StructLiteralExp));
1213                 se->sym = irs->shidden;
1214                 se->soffset = 0;
1215                 se->fillHoles = 1;
1216                 e = exp->toElem(irs);
1217                 memcpy(se, save, sizeof(StructLiteralExp));
1218
1219             }
1220             else
1221                 e = exp->toElem(irs);
1222             assert(e);
1223
1224             if (exp->op == TOKstructliteral ||
1225                 (func->nrvo_can && func->nrvo_var))
1226             {
1227                 // Return value via hidden pointer passed as parameter
1228                 // Write exp; return shidden;
1229                 es = e;
1230             }
1231             else
1232             {
1233                 // Return value via hidden pointer passed as parameter
1234                 // Write *shidden=exp; return shidden;
1235                 int op;
1236                 tym_t ety;
1237
1238                 ety = e->Ety;
1239                 es = el_una(OPind,ety,el_var(irs->shidden));
1240                 op = (tybasic(ety) == TYstruct) ? OPstreq : OPeq;
1241                 es = el_bin(op, ety, es, e);
1242                 if (op == OPstreq)
1243                     es->ET = exp->type->toCtype();
1244 #if DMDV2
1245                 /* Call postBlit() on *shidden
1246                  */
1247                 Type *tb = exp->type->toBasetype();
1248                 //if (tb->ty == Tstruct) exp->dump(0);
1249                 if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar) &&
1250                     tb->ty == Tstruct)
1251                 {   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
1252                     if (sd->postblit)
1253                     {   FuncDeclaration *fd = sd->postblit;
1254                         elem *ec = el_var(irs->shidden);
1255                         ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL);
1256                         es = el_bin(OPcomma, ec->Ety, es, ec);
1257                     }
1258
1259 #if 0
1260                     /* It has been moved, so disable destructor
1261                      */
1262                     if (exp->op == TOKvar)
1263                     {   VarExp *ve = (VarExp *)exp;
1264                         VarDeclaration *v = ve->var->isVarDeclaration();
1265                         if (v && v->rundtor)
1266                         {
1267                             elem *er = el_var(v->rundtor->toSymbol());
1268                             er = el_bin(OPeq, TYint, er, el_long(TYint, 0));
1269                             es = el_bin(OPcomma, TYint, es, er);
1270                         }
1271                     }
1272 #endif
1273                 }
1274 #endif
1275             }
1276             e = el_var(irs->shidden);
1277             e = el_bin(OPcomma, e->Ety, es, e);
1278         }
1279 #if DMDV2
1280         else if (tf->isref)
1281         {   // Reference return, so convert to a pointer
1282             Expression *ae = exp->addressOf(NULL);
1283             e = ae->toElem(irs);
1284         }
1285 #endif
1286         else
1287         {
1288             e = exp->toElem(irs);
1289             assert(e);
1290         }
1291
1292         block_appendexp(blx->curblock, e);
1293         block_next(blx, BCretexp, NULL);
1294     }
1295     else
1296         block_next(blx, BCret, NULL);
1297 }
1298
1299 /**************************************
1300  */
1301
1302 void ExpStatement::toIR(IRState *irs)
1303 {
1304     Blockx *blx = irs->blx;
1305
1306     //printf("ExpStatement::toIR(), exp = %s\n", exp ? exp->toChars() : "");
1307     incUsage(irs, loc);
1308     if (exp)
1309         block_appendexp(blx->curblock,exp->toElem(irs));
1310 }
1311
1312 /**************************************
1313  */
1314
1315 void CompoundStatement::toIR(IRState *irs)
1316 {
1317     if (statements)
1318     {
1319         size_t dim = statements->dim;
1320         for (size_t i = 0 ; i < dim ; i++)
1321         {
1322             Statement *s = (Statement *)statements->data[i];
1323             if (s != NULL)
1324             {
1325                 s->toIR(irs);
1326             }
1327         }
1328     }
1329 }
1330
1331
1332 /**************************************
1333  */
1334
1335 void UnrolledLoopStatement::toIR(IRState *irs)
1336 {
1337     Blockx *blx = irs->blx;
1338
1339     IRState mystate(irs, this);
1340     mystate.breakBlock = block_calloc(blx);
1341
1342     block *bpre = blx->curblock;
1343     block_next(blx, BCgoto, NULL);
1344
1345     block *bdo = blx->curblock;
1346     list_append(&bpre->Bsucc, bdo);
1347
1348     block *bdox;
1349
1350     size_t dim = statements->dim;
1351     for (size_t i = 0 ; i < dim ; i++)
1352     {
1353         Statement *s = (Statement *)statements->data[i];
1354         if (s != NULL)
1355         {
1356             mystate.contBlock = block_calloc(blx);
1357
1358             s->toIR(&mystate);
1359
1360             bdox = blx->curblock;
1361             block_next(blx, BCgoto, mystate.contBlock);
1362             list_append(&bdox->Bsucc, mystate.contBlock);
1363         }
1364     }
1365
1366     bdox = blx->curblock;
1367     block_next(blx, BCgoto, mystate.breakBlock);
1368     list_append(&bdox->Bsucc, mystate.breakBlock);
1369 }
1370
1371
1372 /**************************************
1373  */
1374
1375 void ScopeStatement::toIR(IRState *irs)
1376 {
1377     if (statement)
1378     {
1379         Blockx *blx = irs->blx;
1380         IRState mystate(irs,this);
1381
1382         if (mystate.prev->ident)
1383             mystate.ident = mystate.prev->ident;
1384
1385         statement->toIR(&mystate);
1386
1387         if (mystate.breakBlock)
1388             block_goto(blx,BCgoto,mystate.breakBlock);
1389     }
1390 }
1391
1392 /***************************************
1393  */
1394
1395 void WithStatement::toIR(IRState *irs)
1396 {
1397     Symbol *sp;
1398     elem *e;
1399     elem *ei;
1400     ExpInitializer *ie;
1401     Blockx *blx = irs->blx;
1402
1403     //printf("WithStatement::toIR()\n");
1404     if (exp->op == TOKimport || exp->op == TOKtype)
1405     {
1406     }
1407     else
1408     {
1409         // Declare with handle
1410         sp = wthis->toSymbol();
1411         symbol_add(sp);
1412
1413         // Perform initialization of with handle
1414         ie = wthis->init->isExpInitializer();
1415         assert(ie);
1416         ei = ie->exp->toElem(irs);
1417         e = el_var(sp);
1418         e = el_bin(OPeq,e->Ety, e, ei);
1419         elem_setLoc(e, loc);
1420         incUsage(irs, loc);
1421         block_appendexp(blx->curblock,e);
1422     }
1423     // Execute with block
1424     if (body)
1425         body->toIR(irs);
1426 }
1427
1428
1429 /***************************************
1430  */
1431
1432 void ThrowStatement::toIR(IRState *irs)
1433 {
1434     // throw(exp)
1435
1436     Blockx *blx = irs->blx;
1437
1438     incUsage(irs, loc);
1439     elem *e = exp->toElem(irs);
1440     e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_THROWC]),e);
1441     block_appendexp(blx->curblock, e);
1442 }
1443
1444 /***************************************
1445  * Builds the following:
1446  *      _try
1447  *      block
1448  *      jcatch
1449  *      handler
1450  * A try-catch statement.
1451  */
1452
1453 void TryCatchStatement::toIR(IRState *irs)
1454 {
1455     Blockx *blx = irs->blx;
1456
1457 #if SEH
1458     nteh_declarvars(blx);
1459 #endif
1460
1461     IRState mystate(irs, this);
1462
1463     block *tryblock = block_goto(blx,BCgoto,NULL);
1464
1465     int previndex = blx->scope_index;
1466     tryblock->Blast_index = previndex;
1467     blx->scope_index = tryblock->Bscope_index = blx->next_index++;
1468
1469     // Set the current scope index
1470     setScopeIndex(blx,tryblock,tryblock->Bscope_index);
1471
1472     // This is the catch variable
1473     tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));
1474
1475     blx->tryblock = tryblock;
1476     block *breakblock = block_calloc(blx);
1477     block_goto(blx,BC_try,NULL);
1478     if (body)
1479     {
1480         body->toIR(&mystate);
1481     }
1482     blx->tryblock = tryblock->Btry;
1483
1484     // break block goes here
1485     block_goto(blx, BCgoto, breakblock);
1486
1487     setScopeIndex(blx,blx->curblock, previndex);
1488     blx->scope_index = previndex;
1489
1490     // create new break block that follows all the catches
1491     breakblock = block_calloc(blx);
1492
1493     list_append(&blx->curblock->Bsucc, breakblock);
1494     block_next(blx,BCgoto,NULL);
1495
1496     assert(catches);
1497     for (int i = 0 ; i < catches->dim; i++)
1498     {
1499         Catch *cs = (Catch *)(catches->data[i]);
1500         if (cs->var)
1501             cs->var->csym = tryblock->jcatchvar;
1502         block *bcatch = blx->curblock;
1503         if (cs->type)
1504             bcatch->Bcatchtype = cs->type->toBasetype()->toSymbol();
1505         list_append(&tryblock->Bsucc,bcatch);
1506         block_goto(blx,BCjcatch,NULL);
1507         if (cs->handler != NULL)
1508         {
1509             IRState catchState(irs, this);
1510             cs->handler->toIR(&catchState);
1511         }
1512         list_append(&blx->curblock->Bsucc, breakblock);
1513         block_next(blx, BCgoto, NULL);
1514     }
1515
1516     block_next(blx,(enum BC)blx->curblock->BC, breakblock);
1517 }
1518
1519 /****************************************
1520  * A try-finally statement.
1521  * Builds the following:
1522  *      _try
1523  *      block
1524  *      _finally
1525  *      finalbody
1526  *      _ret
1527  */
1528
1529 void TryFinallyStatement::toIR(IRState *irs)
1530 {
1531     //printf("TryFinallyStatement::toIR()\n");
1532
1533     Blockx *blx = irs->blx;
1534
1535 #if SEH
1536     nteh_declarvars(blx);
1537 #endif
1538
1539     block *tryblock = block_goto(blx, BCgoto, NULL);
1540
1541     int previndex = blx->scope_index;
1542     tryblock->Blast_index = previndex;
1543     tryblock->Bscope_index = blx->next_index++;
1544     blx->scope_index = tryblock->Bscope_index;
1545
1546     // Current scope index
1547     setScopeIndex(blx,tryblock,tryblock->Bscope_index);
1548
1549     blx->tryblock = tryblock;
1550     block_goto(blx,BC_try,NULL);
1551
1552     IRState bodyirs(irs, this);
1553     block *breakblock = block_calloc(blx);
1554     block *contblock = block_calloc(blx);
1555
1556     if (body)
1557         body->toIR(&bodyirs);
1558     blx->tryblock = tryblock->Btry;     // back to previous tryblock
1559
1560     setScopeIndex(blx,blx->curblock,previndex);
1561     blx->scope_index = previndex;
1562
1563     block_goto(blx,BCgoto, breakblock);
1564     block *finallyblock = block_goto(blx,BCgoto,contblock);
1565
1566     list_append(&tryblock->Bsucc,finallyblock);
1567
1568     block_goto(blx,BC_finally,NULL);
1569
1570     IRState finallyState(irs, this);
1571     breakblock = block_calloc(blx);
1572     contblock = block_calloc(blx);
1573
1574     setScopeIndex(blx, blx->curblock, previndex);
1575     if (finalbody)
1576         finalbody->toIR(&finallyState);
1577     block_goto(blx, BCgoto, contblock);
1578     block_goto(blx, BCgoto, breakblock);
1579
1580     block *retblock = blx->curblock;
1581     block_next(blx,BC_ret,NULL);
1582
1583     list_append(&finallyblock->Bsucc, blx->curblock);
1584     list_append(&retblock->Bsucc, blx->curblock);
1585 }
1586
1587 /****************************************
1588  */
1589
1590 void SynchronizedStatement::toIR(IRState *irs)
1591 {
1592     assert(0);
1593 }
1594
1595
1596 /****************************************
1597  */
1598
1599 void AsmStatement::toIR(IRState *irs)
1600 {
1601     block *bpre;
1602     block *basm;
1603     Declaration *d;
1604     Symbol *s;
1605     Blockx *blx = irs->blx;
1606
1607     //printf("AsmStatement::toIR(asmcode = %x)\n", asmcode);
1608     bpre = blx->curblock;
1609     block_next(blx,BCgoto,NULL);
1610     basm = blx->curblock;
1611     list_append(&bpre->Bsucc, basm);
1612     basm->Bcode = asmcode;
1613     basm->Balign = asmalign;
1614 #if 0
1615     if (label)
1616     {   block *b;
1617
1618         b = labelToBlock(loc, blx, label);
1619         printf("AsmStatement::toIR() %p\n", b);
1620         if (b)
1621             list_append(&basm->Bsucc, b);
1622     }
1623 #endif
1624     // Loop through each instruction, fixing Dsymbols into Symbol's
1625     for (code *c = asmcode; c; c = c->next)
1626     {   LabelDsymbol *label;
1627         block *b;
1628
1629         switch (c->IFL1)
1630         {
1631             case FLblockoff:
1632             case FLblock:
1633                 // FLblock and FLblockoff have LabelDsymbol's - convert to blocks
1634                 label = c->IEVlsym1;
1635                 b = labelToBlock(loc, blx, label);
1636                 list_append(&basm->Bsucc, b);
1637                 c->IEV1.Vblock = b;
1638                 break;
1639
1640             case FLdsymbol:
1641             case FLfunc:
1642                 s = c->IEVdsym1->toSymbol();
1643                 if (s->Sclass == SCauto && s->Ssymnum == -1)
1644                     symbol_add(s);
1645                 c->IEVsym1 = s;
1646                 c->IFL1 = s->Sfl ? s->Sfl : FLauto;
1647                 break;
1648         }
1649
1650         // Repeat for second operand
1651         switch (c->IFL2)
1652         {
1653             case FLblockoff:
1654             case FLblock:
1655                 label = c->IEVlsym2;
1656                 b = labelToBlock(loc, blx, label);
1657                 list_append(&basm->Bsucc, b);
1658                 c->IEV2.Vblock = b;
1659                 break;
1660
1661             case FLdsymbol:
1662             case FLfunc:
1663                 d = c->IEVdsym2;
1664                 s = d->toSymbol();
1665                 if (s->Sclass == SCauto && s->Ssymnum == -1)
1666                     symbol_add(s);
1667                 c->IEVsym2 = s;
1668                 c->IFL2 = s->Sfl ? s->Sfl : FLauto;
1669                 if (d->isDataseg())
1670                     s->Sflags |= SFLlivexit;
1671                 break;
1672         }
1673         //c->print();
1674     }
1675
1676     basm->bIasmrefparam = refparam;             // are parameters reference?
1677     basm->usIasmregs = regs;                    // registers modified
1678
1679     block_next(blx,BCasm, NULL);
1680     list_prepend(&basm->Bsucc, blx->curblock);
1681
1682     if (naked)
1683     {
1684         blx->funcsym->Stype->Tty |= mTYnaked;
1685     }
1686 }
Note: See TracBrowser for help on using the browser.