1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 2000-2011 by Digital Mars
4: // All Rights Reserved
5: // Written by Walter Bright
6: // http://www.digitalmars.com
7:
8: #include <stdio.h>
9: #include <string.h>
10: #include <time.h>
11:
12: #include "mars.h"
13: #include "lexer.h"
14: #include "statement.h"
15: #include "expression.h"
16: #include "mtype.h"
17: #include "dsymbol.h"
18: #include "declaration.h"
19: #include "irstate.h"
20: #include "init.h"
21: #include "module.h"
22: #include "enum.h"
23: #include "aggregate.h"
24: #include "template.h"
25: #include "id.h"
26:
27: // Back end
28: #include "cc.h"
29: #include "type.h"
30: #include "code.h"
31: #include "oper.h"
32: #include "global.h"
33: #include "dt.h"
34:
35: #include "rmem.h"
36:
37: static char __file__[] = __FILE__; // for tassert.h
38: #include "tassert.h"
39:
40: elem *callfunc(Loc loc,
41: IRState *irs,
42: int directcall, // 1: don't do virtual call
43: Type *tret, // return type
44: elem *ec, // evaluates to function address
45: Type *ectype, // original type of ec
46: FuncDeclaration *fd, // if !=NULL, this is the function being called
47: Type *t, // TypeDelegate or TypeFunction for this function
48: elem *ehidden, // if !=NULL, this is the 'hidden' argument
49: Expressions *arguments);
50:
51: elem *exp2_copytotemp(elem *e);
52: elem *incUsageElem(IRState *irs, Loc loc);
53: StructDeclaration *needsPostblit(Type *t);
54:
55: #define elem_setLoc(e,loc) ((e)->Esrcpos.Sfilename = (char *)(loc).filename, \
56: (e)->Esrcpos.Slinnum = (loc).linnum)
57:
58: #define SEH (TARGET_WINDOS)
59:
60: /***********************************************
61: * Generate code to set index into scope table.
62: */
63:
64: #if SEH
65: void setScopeIndex(Blockx *blx, block *b, int scope_index)
66: {
67: block_appendexp(b, nteh_setScopeTableIndex(blx, scope_index));
68: }
69: #else
70: #define setScopeIndex(blx, b, scope_index) ;
71: #endif
72:
73: /****************************************
74: * Allocate a new block, and set the tryblock.
75: */
76:
77: block *block_calloc(Blockx *blx)
78: {
79: block *b = block_calloc();
80: b->Btry = blx->tryblock;
81: return b;
82: }
83:
84: /**************************************
85: * Convert label to block.
86: */
87:
88: block *labelToBlock(Loc loc, Blockx *blx, LabelDsymbol *label, int flag = 0)
89: {
90: if (!label->statement)
91: {
92: error(loc, "undefined label %s", label->toChars());
93: return NULL;
94: }
95: LabelStatement *s = label->statement;
96: if (!s->lblock)
97: { s->lblock = block_calloc(blx);
98: s->lblock->Btry = NULL; // fill this in later
99:
100: if (flag)
101: {
102: // Keep track of the forward reference to this block, so we can check it later
103: if (!s->fwdrefs)
104: s->fwdrefs = new Blocks();
105: s->fwdrefs->push(blx->curblock);
106: }
107: }
108: return s->lblock;
109: }
110:
111: /**************************************
112: * Add in code to increment usage count for linnum.
113: */
114:
115: void incUsage(IRState *irs, Loc loc)
116: {
117:
118: if (global.params.cov && loc.linnum)
119: {
120: block_appendexp(irs->blx->curblock, incUsageElem(irs, loc));
121: }
122: }
123:
124: /****************************************
125: * This should be overridden by each statement class.
126: */
127:
128: void Statement::toIR(IRState *irs)
129: {
130: print();
131: assert(0);
132: }
133:
134: /*************************************
135: */
136:
137: void OnScopeStatement::toIR(IRState *irs)
138: {
139: }
140:
141: /****************************************
142: */
143:
144: void IfStatement::toIR(IRState *irs)
145: {
146: elem *e;
147: Blockx *blx = irs->blx;
148:
149: //printf("IfStatement::toIR('%s')\n", condition->toChars());
150:
151: IRState mystate(irs, this);
152:
153: // bexit is the block that gets control after this IfStatement is done
154: block *bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();
155:
156: incUsage(irs, loc);
157: #if 0
158: if (match)
159: { /* Generate:
160: * if (match = RTLSYM_IFMATCH(string, pattern)) ...
161: */
162: assert(condition->op == TOKmatch);
163: e = matchexp_toelem((MatchExp *)condition, &mystate, RTLSYM_IFMATCH);
164: Symbol *s = match->toSymbol();
165: symbol_add(s);
166: e = el_bin(OPeq, TYnptr, el_var(s), e);
167: }
168: else
169: #endif
170: e = condition->toElemDtor(&mystate);
171: block_appendexp(blx->curblock, e);
172: block *bcond = blx->curblock;
173: block_next(blx, BCiftrue, NULL);
174:
175: list_append(&bcond->Bsucc, blx->curblock);
176: if (ifbody)
177: ifbody->toIR(&mystate);
178: list_append(&blx->curblock->Bsucc, bexit);
179:
180: if (elsebody)
181: {
182: block_next(blx, BCgoto, NULL);
183: list_append(&bcond->Bsucc, blx->curblock);
184: elsebody->toIR(&mystate);
185: list_append(&blx->curblock->Bsucc, bexit);
186: }
187: else
188: list_append(&bcond->Bsucc, bexit);
189:
190: block_next(blx, BCgoto, bexit);
191:
192: }
193:
194: /**************************************
195: */
196:
197: #if DMDV2
198: void PragmaStatement::toIR(IRState *irs)
199: {
200: //printf("PragmaStatement::toIR()\n");
201: if (ident == Id::startaddress)
202: {
203: assert(args && args->dim == 1);
204: Expression *e = args->tdata()[0];
205: Dsymbol *sa = getDsymbol(e);
206: FuncDeclaration *f = sa->isFuncDeclaration();
207: assert(f);
208: Symbol *s = f->toSymbol();
209: while (irs->prev)
210: irs = irs->prev;
211: irs->startaddress = s;
212: }
213: }
214: #endif
215:
216: /***********************
217: */
218:
219: void WhileStatement::toIR(IRState *irs)
220: {
221: assert(0); // was "lowered"
222: #if 0
223: Blockx *blx = irs->blx;
224:
225: /* Create a new state, because we need a new continue and break target
226: */
227: IRState mystate(irs,this);
228: mystate.breakBlock = block_calloc(blx);
229: mystate.contBlock = block_calloc(blx);
230:
231: list_append(&blx->curblock->Bsucc, mystate.contBlock);
232: block_next(blx, BCgoto, mystate.contBlock);
233: incUsage(irs, loc);
234: block_appendexp(mystate.contBlock, condition->toElem(&mystate));
235:
236: block_next(blx, BCiftrue, NULL);
237:
238: /* curblock is the start of the while loop body
239: */
240: list_append(&mystate.contBlock->Bsucc, blx->curblock);
241: if (body)
242: body->toIR(&mystate);
243: list_append(&blx->curblock->Bsucc, mystate.contBlock);
244: block_next(blx, BCgoto, mystate.breakBlock);
245:
246: list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
247: #endif
248: }
249:
250: /******************************************
251: */
252:
253: void DoStatement::toIR(IRState *irs)
254: {
255: Blockx *blx = irs->blx;
256:
257: IRState mystate(irs,this);
258: mystate.breakBlock = block_calloc(blx);
259: mystate.contBlock = block_calloc(blx);
260:
261: block *bpre = blx->curblock;
262: block_next(blx, BCgoto, NULL);
263: list_append(&bpre->Bsucc, blx->curblock);
264:
265: list_append(&mystate.contBlock->Bsucc, blx->curblock);
266: list_append(&mystate.contBlock->Bsucc, mystate.breakBlock);
267:
268: if (body)
269: body->toIR(&mystate);
270: list_append(&blx->curblock->Bsucc, mystate.contBlock);
271:
272: block_next(blx, BCgoto, mystate.contBlock);
273: incUsage(irs, condition->loc);
274: block_appendexp(mystate.contBlock, condition->toElemDtor(&mystate));
275: block_next(blx, BCiftrue, mystate.breakBlock);
276:
277: }
278:
279: /*****************************************
280: */
281:
282: void ForStatement::toIR(IRState *irs)
283: {
284: Blockx *blx = irs->blx;
285:
286: IRState mystate(irs,this);
287: mystate.breakBlock = block_calloc(blx);
288: mystate.contBlock = block_calloc(blx);
289:
290: if (init)
291: init->toIR(&mystate);
292: block *bpre = blx->curblock;
293: block_next(blx,BCgoto,NULL);
294: block *bcond = blx->curblock;
295: list_append(&bpre->Bsucc, bcond);
296: list_append(&mystate.contBlock->Bsucc, bcond);
297: if (condition)
298: {
299: incUsage(irs, condition->loc);
300: block_appendexp(bcond, condition->toElemDtor(&mystate));
301: block_next(blx,BCiftrue,NULL);
302: list_append(&bcond->Bsucc, blx->curblock);
303: list_append(&bcond->Bsucc, mystate.breakBlock);
304: }
305: else
306: { /* No conditional, it's a straight goto
307: */
308: block_next(blx,BCgoto,NULL);
309: list_append(&bcond->Bsucc, blx->curblock);
310: }
311:
312: if (body)
313: body->toIR(&mystate);
314: /* End of the body goes to the continue block
315: */
316: list_append(&blx->curblock->Bsucc, mystate.contBlock);
317: block_next(blx, BCgoto, mystate.contBlock);
318:
319: if (increment)
320: {
321: incUsage(irs, increment->loc);
322: block_appendexp(mystate.contBlock, increment->toElemDtor(&mystate));
323: }
324:
325: /* The 'break' block follows the for statement.
326: */
327: block_next(blx,BCgoto, mystate.breakBlock);
328: }
329:
330:
331: /**************************************
332: */
333:
334: void ForeachStatement::toIR(IRState *irs)
335: {
336: printf("ForeachStatement::toIR() %s\n", toChars());
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++)
warning C4018: '<' : signed/unsigned mismatch
871: { block *b = fwdrefs->tdata()[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->toElemDtor(&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 = cases->tdata()[i];
944:
945: elem *ecase = cs->exp->toElemDtor(&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 = cases->tdata()[i];
977: cs->index = i;
978: }
979:
980: cases->sort();
warning C6011: Dereferencing NULL pointer 'cases': Lines: 905, 906, 909, 911, 915, 923, 925, 926, 929, 930, 932, 972, 975, 980
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 = cases->tdata()[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;
warning C6011: Dereferencing NULL pointer 'pu++': Lines: 905, 906, 909, 911, 915, 923, 925, 926, 927, 929, 930, 932, 972, 975, 980, 985, 986, 990, 991, 993, 1008, 1009, 1010, 1015, 1016, 1018, 1019, 1030, 1031, 1035, 1036, 1039, 1040, 1043
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 = cases->tdata()[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->toElemDtor(irs);
1217: memcpy(se, save, sizeof(StructLiteralExp));
1218:
1219: }
1220: else
1221: e = exp->toElemDtor(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 || exp->op == TOKthis) &&
1250: tb->ty == Tstruct)
1251: { StructDeclaration *sd = ((TypeStruct *)tb)->sym;
1252: if (sd->postblit)
1253: { FuncDeclaration *fd = sd->postblit;
1254: if (fd->storage_class & STCdisable)
1255: {
1256: fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
1257: }
1258: elem *ec = el_var(irs->shidden);
1259: ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL);
1260: es = el_bin(OPcomma, ec->Ety, es, ec);
1261: }
1262:
1263: #if 0
1264: /* It has been moved, so disable destructor
1265: */
1266: if (exp->op == TOKvar)
1267: { VarExp *ve = (VarExp *)exp;
1268: VarDeclaration *v = ve->var->isVarDeclaration();
1269: if (v && v->rundtor)
1270: {
1271: elem *er = el_var(v->rundtor->toSymbol());
1272: er = el_bin(OPeq, TYint, er, el_long(TYint, 0));
1273: es = el_bin(OPcomma, TYint, es, er);
1274: }
1275: }
1276: #endif
1277: }
1278: #endif
1279: }
1280: e = el_var(irs->shidden);
1281: e = el_bin(OPcomma, e->Ety, es, e);
1282: }
1283: #if DMDV2
1284: else if (tf->isref)
1285: { // Reference return, so convert to a pointer
1286: Expression *ae = exp->addressOf(NULL);
1287: e = ae->toElemDtor(irs);
1288: }
1289: #endif
1290: else
1291: {
1292: e = exp->toElemDtor(irs);
1293: assert(e);
1294: }
1295:
1296: elem_setLoc(e, loc);
1297: block_appendexp(blx->curblock, e);
1298: block_next(blx, BCretexp, NULL);
1299: }
1300: else
1301: block_next(blx, BCret, NULL);
1302: }
1303:
1304: /**************************************
1305: */
1306:
1307: void ExpStatement::toIR(IRState *irs)
1308: {
1309: Blockx *blx = irs->blx;
1310:
1311: //printf("ExpStatement::toIR(), exp = %s\n", exp ? exp->toChars() : "");
1312: incUsage(irs, loc);
1313: if (exp)
1314: block_appendexp(blx->curblock,exp->toElemDtor(irs));
1315: }
1316:
1317: /**************************************
1318: */
1319:
1320: void DtorExpStatement::toIR(IRState *irs)
1321: {
1322: //printf("DtorExpStatement::toIR(), exp = %s\n", exp ? exp->toChars() : "");
1323:
1324: FuncDeclaration *fd = irs->getFunc();
1325: assert(fd);
1326: if (fd->nrvo_can && fd->nrvo_var == var)
1327: /* Do not call destructor, because var is returned as the nrvo variable.
1328: * This is done at this stage because nrvo can be turned off at a
1329: * very late stage in semantic analysis.
1330: */
1331: ;
1332: else
1333: {
1334: ExpStatement::toIR(irs);
1335: }
1336: }
1337:
1338: /**************************************
1339: */
1340:
1341: void CompoundStatement::toIR(IRState *irs)
1342: {
1343: if (statements)
1344: {
1345: size_t dim = statements->dim;
1346: for (size_t i = 0 ; i < dim ; i++)
1347: {
1348: Statement *s = statements->tdata()[i];
1349: if (s != NULL)
1350: {
1351: s->toIR(irs);
1352: }
1353: }
1354: }
1355: }
1356:
1357:
1358: /**************************************
1359: */
1360:
1361: void UnrolledLoopStatement::toIR(IRState *irs)
1362: {
1363: Blockx *blx = irs->blx;
1364:
1365: IRState mystate(irs, this);
1366: mystate.breakBlock = block_calloc(blx);
1367:
1368: block *bpre = blx->curblock;
1369: block_next(blx, BCgoto, NULL);
1370:
1371: block *bdo = blx->curblock;
1372: list_append(&bpre->Bsucc, bdo);
1373:
1374: block *bdox;
1375:
1376: size_t dim = statements->dim;
1377: for (size_t i = 0 ; i < dim ; i++)
1378: {
1379: Statement *s = statements->tdata()[i];
1380: if (s != NULL)
1381: {
1382: mystate.contBlock = block_calloc(blx);
1383:
1384: s->toIR(&mystate);
1385:
1386: bdox = blx->curblock;
1387: block_next(blx, BCgoto, mystate.contBlock);
1388: list_append(&bdox->Bsucc, mystate.contBlock);
1389: }
1390: }
1391:
1392: bdox = blx->curblock;
1393: block_next(blx, BCgoto, mystate.breakBlock);
1394: list_append(&bdox->Bsucc, mystate.breakBlock);
1395: }
1396:
1397:
1398: /**************************************
1399: */
1400:
1401: void ScopeStatement::toIR(IRState *irs)
1402: {
1403: if (statement)
1404: {
1405: Blockx *blx = irs->blx;
1406: IRState mystate(irs,this);
1407:
1408: if (mystate.prev->ident)
1409: mystate.ident = mystate.prev->ident;
1410:
1411: statement->toIR(&mystate);
1412:
1413: if (mystate.breakBlock)
1414: block_goto(blx,BCgoto,mystate.breakBlock);
1415: }
1416: }
1417:
1418: /***************************************
1419: */
1420:
1421: void WithStatement::toIR(IRState *irs)
1422: {
1423: Symbol *sp;
1424: elem *e;
1425: elem *ei;
1426: ExpInitializer *ie;
1427: Blockx *blx = irs->blx;
1428:
1429: //printf("WithStatement::toIR()\n");
1430: if (exp->op == TOKimport || exp->op == TOKtype)
1431: {
1432: }
1433: else
1434: {
1435: // Declare with handle
1436: sp = wthis->toSymbol();
1437: symbol_add(sp);
1438:
1439: // Perform initialization of with handle
1440: ie = wthis->init->isExpInitializer();
1441: assert(ie);
1442: ei = ie->exp->toElemDtor(irs);
1443: e = el_var(sp);
1444: e = el_bin(OPeq,e->Ety, e, ei);
1445: elem_setLoc(e, loc);
1446: incUsage(irs, loc);
1447: block_appendexp(blx->curblock,e);
1448: }
1449: // Execute with block
1450: if (body)
1451: body->toIR(irs);
1452: }
1453:
1454:
1455: /***************************************
1456: */
1457:
1458: void ThrowStatement::toIR(IRState *irs)
1459: {
1460: // throw(exp)
1461:
1462: Blockx *blx = irs->blx;
1463:
1464: incUsage(irs, loc);
1465: elem *e = exp->toElemDtor(irs);
1466: e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_THROWC]),e);
1467: block_appendexp(blx->curblock, e);
1468: }
1469:
1470: /***************************************
1471: * Builds the following:
1472: * _try
1473: * block
1474: * jcatch
1475: * handler
1476: * A try-catch statement.
1477: */
1478:
1479: void TryCatchStatement::toIR(IRState *irs)
1480: {
1481: Blockx *blx = irs->blx;
1482:
1483: #if SEH
1484: nteh_declarvars(blx);
1485: #endif
1486:
1487: IRState mystate(irs, this);
1488:
1489: block *tryblock = block_goto(blx,BCgoto,NULL);
1490:
1491: int previndex = blx->scope_index;
1492: tryblock->Blast_index = previndex;
1493: blx->scope_index = tryblock->Bscope_index = blx->next_index++;
1494:
1495: // Set the current scope index
1496: setScopeIndex(blx,tryblock,tryblock->Bscope_index);
1497:
1498: // This is the catch variable
1499: tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));
1500:
1501: blx->tryblock = tryblock;
1502: block *breakblock = block_calloc(blx);
1503: block_goto(blx,BC_try,NULL);
1504: if (body)
1505: {
1506: body->toIR(&mystate);
1507: }
1508: blx->tryblock = tryblock->Btry;
1509:
1510: // break block goes here
1511: block_goto(blx, BCgoto, breakblock);
1512:
1513: setScopeIndex(blx,blx->curblock, previndex);
1514: blx->scope_index = previndex;
1515:
1516: // create new break block that follows all the catches
1517: breakblock = block_calloc(blx);
1518:
1519: list_append(&blx->curblock->Bsucc, breakblock);
1520: block_next(blx,BCgoto,NULL);
1521:
1522: assert(catches);
1523: for (int i = 0 ; i < catches->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1524: {
1525: Catch *cs = catches->tdata()[i];
1526: if (cs->var)
1527: cs->var->csym = tryblock->jcatchvar;
1528: block *bcatch = blx->curblock;
1529: if (cs->type)
1530: bcatch->Bcatchtype = cs->type->toBasetype()->toSymbol();
1531: list_append(&tryblock->Bsucc,bcatch);
1532: block_goto(blx,BCjcatch,NULL);
1533: if (cs->handler != NULL)
1534: {
1535: IRState catchState(irs, this);
1536: cs->handler->toIR(&catchState);
1537: }
1538: list_append(&blx->curblock->Bsucc, breakblock);
1539: block_next(blx, BCgoto, NULL);
1540: }
1541:
1542: block_next(blx,(enum BC)blx->curblock->BC, breakblock);
1543: }
1544:
1545: /****************************************
1546: * A try-finally statement.
1547: * Builds the following:
1548: * _try
1549: * block
1550: * _finally
1551: * finalbody
1552: * _ret
1553: */
1554:
1555: void TryFinallyStatement::toIR(IRState *irs)
1556: {
1557: //printf("TryFinallyStatement::toIR()\n");
1558:
1559: Blockx *blx = irs->blx;
1560:
1561: #if SEH
1562: nteh_declarvars(blx);
1563: #endif
1564:
1565: block *tryblock = block_goto(blx, BCgoto, NULL);
1566:
1567: int previndex = blx->scope_index;
1568: tryblock->Blast_index = previndex;
1569: tryblock->Bscope_index = blx->next_index++;
1570: blx->scope_index = tryblock->Bscope_index;
1571:
1572: // Current scope index
1573: setScopeIndex(blx,tryblock,tryblock->Bscope_index);
1574:
1575: blx->tryblock = tryblock;
1576: block_goto(blx,BC_try,NULL);
1577:
1578: IRState bodyirs(irs, this);
1579: block *breakblock = block_calloc(blx);
1580: block *contblock = block_calloc(blx);
1581:
1582: if (body)
1583: body->toIR(&bodyirs);
1584: blx->tryblock = tryblock->Btry; // back to previous tryblock
1585:
1586: setScopeIndex(blx,blx->curblock,previndex);
1587: blx->scope_index = previndex;
1588:
1589: block_goto(blx,BCgoto, breakblock);
1590: block *finallyblock = block_goto(blx,BCgoto,contblock);
1591:
1592: list_append(&tryblock->Bsucc,finallyblock);
1593:
1594: block_goto(blx,BC_finally,NULL);
1595:
1596: IRState finallyState(irs, this);
1597: breakblock = block_calloc(blx);
1598: contblock = block_calloc(blx);
1599:
1600: setScopeIndex(blx, blx->curblock, previndex);
1601: if (finalbody)
1602: finalbody->toIR(&finallyState);
1603: block_goto(blx, BCgoto, contblock);
1604: block_goto(blx, BCgoto, breakblock);
1605:
1606: block *retblock = blx->curblock;
1607: block_next(blx,BC_ret,NULL);
1608:
1609: list_append(&finallyblock->Bsucc, blx->curblock);
1610: list_append(&retblock->Bsucc, blx->curblock);
1611: }
1612:
1613: /****************************************
1614: */
1615:
1616: void SynchronizedStatement::toIR(IRState *irs)
1617: {
1618: assert(0);
1619: }
1620:
1621:
1622: /****************************************
1623: */
1624:
1625: void AsmStatement::toIR(IRState *irs)
1626: {
1627: block *bpre;
1628: block *basm;
1629: Declaration *d;
1630: Symbol *s;
1631: Blockx *blx = irs->blx;
1632:
1633: //printf("AsmStatement::toIR(asmcode = %x)\n", asmcode);
1634: bpre = blx->curblock;
1635: block_next(blx,BCgoto,NULL);
1636: basm = blx->curblock;
1637: list_append(&bpre->Bsucc, basm);
1638: basm->Bcode = asmcode;
1639: basm->Balign = asmalign;
1640: #if 0
1641: if (label)
1642: { block *b;
1643:
1644: b = labelToBlock(loc, blx, label);
1645: printf("AsmStatement::toIR() %p\n", b);
1646: if (b)
1647: list_append(&basm->Bsucc, b);
1648: }
1649: #endif
1650: // Loop through each instruction, fixing Dsymbols into Symbol's
1651: for (code *c = asmcode; c; c = c->next)
1652: { LabelDsymbol *label;
1653: block *b;
1654:
1655: switch (c->IFL1)
1656: {
1657: case FLblockoff:
1658: case FLblock:
1659: // FLblock and FLblockoff have LabelDsymbol's - convert to blocks
1660: label = c->IEVlsym1;
1661: b = labelToBlock(loc, blx, label);
1662: list_append(&basm->Bsucc, b);
1663: c->IEV1.Vblock = b;
1664: break;
1665:
1666: case FLdsymbol:
1667: case FLfunc:
1668: s = c->IEVdsym1->toSymbol();
1669: if (s->Sclass == SCauto && s->Ssymnum == -1)
1670: symbol_add(s);
1671: c->IEVsym1 = s;
1672: c->IFL1 = s->Sfl ? s->Sfl : FLauto;
1673: break;
1674: }
1675:
1676: // Repeat for second operand
1677: switch (c->IFL2)
1678: {
1679: case FLblockoff:
1680: case FLblock:
1681: label = c->IEVlsym2;
1682: b = labelToBlock(loc, blx, label);
1683: list_append(&basm->Bsucc, b);
1684: c->IEV2.Vblock = b;
1685: break;
1686:
1687: case FLdsymbol:
1688: case FLfunc:
1689: d = c->IEVdsym2;
1690: s = d->toSymbol();
1691: if (s->Sclass == SCauto && s->Ssymnum == -1)
1692: symbol_add(s);
1693: c->IEVsym2 = s;
1694: c->IFL2 = s->Sfl ? s->Sfl : FLauto;
1695: if (d->isDataseg())
1696: s->Sflags |= SFLlivexit;
1697: break;
1698: }
1699: //c->print();
1700: }
1701:
1702: basm->bIasmrefparam = refparam; // are parameters reference?
1703: basm->usIasmregs = regs; // registers modified
1704:
1705: block_next(blx,BCasm, NULL);
1706: list_prepend(&basm->Bsucc, blx->curblock);
1707:
1708: if (naked)
1709: {
1710: blx->funcsym->Stype->Tty |= mTYnaked;
1711: }
1712: }
1713:
1714: /****************************************
1715: */
1716:
1717: void ImportStatement::toIR(IRState *irs)
1718: {
1719: }
1720:
1721:
1722:
1723: