0
|
1 module dmd.GotoStatement;
|
|
2
|
|
3 import dmd.Loc;
|
|
4 import dmd.Scope;
|
|
5 import dmd.Statement;
|
|
6 import dmd.Identifier;
|
|
7 import dmd.CompoundStatement;
|
|
8 import dmd.LabelDsymbol;
|
|
9 import dmd.TryFinallyStatement;
|
|
10 import dmd.FuncDeclaration;
|
|
11 import dmd.OutBuffer;
|
|
12 import dmd.HdrGenState;
|
|
13 import dmd.Expression;
|
|
14 import dmd.InterState;
|
|
15 import dmd.IRState;
|
|
16 import dmd.ArrayTypes;
|
|
17 import dmd.BE;
|
|
18
|
|
19 import dmd.codegen.Util;
|
|
20 import dmd.backend.Util;
|
|
21 import dmd.backend.block;
|
|
22 import dmd.backend.Blockx;
|
|
23 import dmd.backend.BC;
|
|
24
|
|
25 class GotoStatement : Statement
|
|
26 {
|
|
27 Identifier ident;
|
|
28 LabelDsymbol label = null;
|
|
29 TryFinallyStatement tf = null;
|
|
30
|
|
31 this(Loc loc, Identifier ident)
|
|
32 {
|
|
33 super(loc);
|
|
34 this.ident = ident;
|
|
35 }
|
|
36
|
|
37 Statement syntaxCopy()
|
|
38 {
|
|
39 GotoStatement s = new GotoStatement(loc, ident);
|
|
40 return s;
|
|
41 }
|
|
42
|
|
43 Statement semantic(Scope sc)
|
|
44 {
|
|
45 FuncDeclaration fd = sc.parent.isFuncDeclaration();
|
|
46
|
|
47 //printf("GotoStatement.semantic()\n");
|
|
48 tf = sc.tf;
|
|
49 label = fd.searchLabel(ident);
|
|
50 if (!label.statement && sc.fes)
|
|
51 {
|
|
52 /* Either the goto label is forward referenced or it
|
|
53 * is in the function that the enclosing foreach is in.
|
|
54 * Can't know yet, so wrap the goto in a compound statement
|
|
55 * so we can patch it later, and add it to a 'look at this later'
|
|
56 * list.
|
|
57 */
|
|
58 Statements a = new Statements();
|
|
59 Statement s;
|
|
60
|
|
61 a.push(cast(void*)this);
|
|
62 s = new CompoundStatement(loc, a);
|
|
63 sc.fes.gotos.push(cast(void*)s); // 'look at this later' list
|
|
64 return s;
|
|
65 }
|
|
66
|
|
67 if (label.statement && label.statement.tf != sc.tf)
|
|
68 error("cannot goto in or out of finally block");
|
|
69 return this;
|
|
70 }
|
|
71
|
|
72 BE blockExit()
|
|
73 {
|
|
74 //printf("GotoStatement.blockExit(%p)\n", this);
|
|
75 return BE.BEgoto;
|
|
76 }
|
|
77
|
63
|
78 Expression interpret(InterState istate)
|
0
|
79 {
|
|
80 assert(false);
|
|
81 }
|
|
82
|
|
83 void toIR(IRState* irs)
|
|
84 {
|
|
85 block* b;
|
|
86 block* bdest;
|
|
87 Blockx* blx = irs.blx;
|
|
88
|
|
89 if (!label.statement)
|
|
90 {
|
|
91 error("label %s is undefined", label.toChars());
|
|
92 return;
|
|
93 }
|
|
94 if (tf !is label.statement.tf)
|
|
95 error("cannot goto forward out of or into finally block");
|
|
96
|
|
97 bdest = labelToBlock(loc, blx, label);
|
|
98 if (!bdest)
|
|
99 return;
|
|
100 b = blx.curblock;
|
|
101 incUsage(irs, loc);
|
|
102
|
|
103 // Adjust exception handler scope index if in different try blocks
|
|
104 if (b.Btry != bdest.Btry)
|
|
105 {
|
|
106 // Check that bdest is in an enclosing try block
|
|
107 for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry)
|
|
108 {
|
|
109 if (!bt)
|
|
110 {
|
|
111 //printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry);
|
|
112 error("cannot goto into try block");
|
|
113 break;
|
|
114 }
|
|
115 }
|
|
116
|
|
117 //setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1);
|
|
118 }
|
|
119
|
|
120 list_append(&b.Bsucc,bdest);
|
|
121 block_next(blx,BCgoto,null);
|
|
122 }
|
|
123
|
|
124 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
|
125 {
|
|
126 buf.writestring("goto ");
|
|
127 buf.writestring(ident.toChars());
|
|
128 buf.writebyte(';');
|
|
129 buf.writenl();
|
|
130 }
|
|
131
|
|
132 GotoStatement isGotoStatement() { return this; }
|
|
133 } |