0
|
1 module dmd.SynchronizedStatement;
|
|
2
|
114
|
3 import dmd.common;
|
0
|
4 import dmd.Statement;
|
|
5 import dmd.IntegerExp;
|
|
6 import dmd.TypeSArray;
|
|
7 import dmd.CompoundStatement;
|
|
8 import dmd.Loc;
|
|
9 import dmd.Scope;
|
|
10 import dmd.Expression;
|
|
11 import dmd.ClassDeclaration;
|
|
12 import dmd.Id;
|
|
13 import dmd.TypeIdentifier;
|
|
14 import dmd.Type;
|
|
15 import dmd.OutBuffer;
|
|
16 import dmd.HdrGenState;
|
|
17 import dmd.InlineScanState;
|
|
18 import dmd.IRState;
|
|
19 import dmd.CastExp;
|
|
20 import dmd.TryFinallyStatement;
|
|
21 import dmd.ExpStatement;
|
|
22 import dmd.CallExp;
|
|
23 import dmd.DeclarationExp;
|
|
24 import dmd.VarExp;
|
|
25 import dmd.DeclarationStatement;
|
|
26 import dmd.ArrayTypes;
|
|
27 import dmd.Statement;
|
|
28 import dmd.VarDeclaration;
|
|
29 import dmd.ExpInitializer;
|
|
30 import dmd.Lexer;
|
|
31 import dmd.Identifier;
|
|
32 import dmd.FuncDeclaration;
|
|
33 import dmd.BE;
|
|
34 import dmd.STC;
|
|
35 import dmd.DotIdExp;
|
|
36
|
|
37 import dmd.backend.elem;
|
|
38 import dmd.backend.Util;
|
|
39
|
|
40 class SynchronizedStatement : Statement
|
|
41 {
|
|
42 Expression exp;
|
|
43 Statement body_;
|
|
44
|
|
45 this(Loc loc, Expression exp, Statement body_)
|
|
46 {
|
|
47 super(loc);
|
|
48
|
|
49 this.exp = exp;
|
|
50 this.body_ = body_;
|
|
51 this.esync = null;
|
|
52 }
|
|
53
|
72
|
54 override Statement syntaxCopy()
|
0
|
55 {
|
|
56 assert(false);
|
|
57 }
|
|
58
|
72
|
59 override Statement semantic(Scope sc)
|
0
|
60 {
|
|
61 if (exp)
|
|
62 {
|
|
63 exp = exp.semantic(sc);
|
|
64 exp = resolveProperties(sc, exp);
|
|
65 ClassDeclaration cd = exp.type.isClassHandle();
|
|
66 if (!cd)
|
|
67 error("can only synchronize on class objects, not '%s'", exp.type.toChars());
|
|
68 else if (cd.isInterfaceDeclaration())
|
|
69 {
|
|
70 /* Cast the interface to an object, as the object has the monitor,
|
|
71 * not the interface.
|
|
72 */
|
|
73 Type t = new TypeIdentifier(Loc(0), Id.Object_);
|
|
74
|
|
75 t = t.semantic(Loc(0), sc);
|
|
76 exp = new CastExp(loc, exp, t);
|
|
77 exp = exp.semantic(sc);
|
|
78 }
|
|
79
|
|
80 static if (true) {
|
|
81 /* Rewrite as:
|
|
82 * auto tmp = exp;
|
|
83 * _d_monitorenter(tmp);
|
|
84 * try { body } finally { _d_monitorexit(tmp); }
|
|
85 */
|
|
86 Identifier id = Lexer.uniqueId("__sync");
|
|
87 ExpInitializer ie = new ExpInitializer(loc, exp);
|
|
88 VarDeclaration tmp = new VarDeclaration(loc, exp.type, id, ie);
|
|
89
|
|
90 Statements cs = new Statements();
|
|
91 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
|
92
|
|
93 FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorenter);
|
|
94 Expression e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
|
|
95 e.type = Type.tvoid; // do not run semantic on e
|
|
96 cs.push(cast(void*)new ExpStatement(loc, e));
|
|
97
|
|
98 FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorexit);
|
|
99 e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
|
|
100 e.type = Type.tvoid; // do not run semantic on e
|
|
101 Statement s = new ExpStatement(loc, e);
|
|
102 s = new TryFinallyStatement(loc, body_, s);
|
|
103 cs.push(cast(void*)s);
|
|
104
|
|
105 s = new CompoundStatement(loc, cs);
|
|
106 return s.semantic(sc);
|
|
107 }
|
|
108 }
|
|
109 /// static if (true) {
|
|
110 else
|
|
111 {
|
|
112 /* Generate our own critical section, then rewrite as:
|
|
113 * __gshared byte[CriticalSection.sizeof] critsec;
|
|
114 * _d_criticalenter(critsec.ptr);
|
|
115 * try { body } finally { _d_criticalexit(critsec.ptr); }
|
|
116 */
|
|
117 Identifier id = Lexer.uniqueId("__critsec");
|
|
118 Type t = new TypeSArray(Type.tint8, new IntegerExp(PTRSIZE + os_critsecsize()));
|
|
119 VarDeclaration tmp = new VarDeclaration(loc, t, id, null);
|
|
120 tmp.storage_class |= STCgshared | STCstatic;
|
|
121
|
|
122 Statements cs = new Statements();
|
|
123 cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
|
|
124
|
|
125 FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalenter);
|
|
126 Expression e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr);
|
|
127 e = e.semantic(sc);
|
|
128 e = new CallExp(loc, new VarExp(loc, fdenter), e);
|
|
129 e.type = Type.tvoid; // do not run semantic on e
|
|
130 cs.push(cast(void*)new ExpStatement(loc, e));
|
|
131
|
|
132 FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalexit);
|
|
133 e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr);
|
|
134 e = e.semantic(sc);
|
|
135 e = new CallExp(loc, new VarExp(loc, fdexit), e);
|
|
136 e.type = Type.tvoid; // do not run semantic on e
|
|
137 Statement s = new ExpStatement(loc, e);
|
|
138 s = new TryFinallyStatement(loc, body_, s);
|
|
139 cs.push(cast(void*)s);
|
|
140
|
|
141 s = new CompoundStatement(loc, cs);
|
|
142 return s.semantic(sc);
|
|
143 }
|
|
144 /// }
|
|
145 if (body_)
|
|
146 body_ = body_.semantic(sc);
|
|
147
|
|
148 return this;
|
|
149 }
|
|
150
|
72
|
151 override bool hasBreak()
|
0
|
152 {
|
|
153 assert(false);
|
|
154 }
|
|
155
|
72
|
156 override bool hasContinue()
|
0
|
157 {
|
|
158 assert(false);
|
|
159 }
|
|
160
|
72
|
161 override bool usesEH()
|
0
|
162 {
|
|
163 assert(false);
|
|
164 }
|
|
165
|
72
|
166 override BE blockExit()
|
0
|
167 {
|
|
168 assert(false);
|
|
169 }
|
|
170
|
72
|
171 override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
|
0
|
172 {
|
|
173 assert(false);
|
|
174 }
|
|
175
|
72
|
176 override Statement inlineScan(InlineScanState* iss)
|
0
|
177 {
|
|
178 assert(false);
|
|
179 }
|
|
180
|
|
181 // Back end
|
|
182 elem* esync;
|
|
183
|
|
184 this(Loc loc, elem *esync, Statement body_)
|
|
185 {
|
|
186 assert(false);
|
|
187 super(loc);
|
|
188 }
|
|
189
|
72
|
190 override void toIR(IRState* irs)
|
0
|
191 {
|
|
192 assert(false);
|
|
193 }
|
72
|
194 }
|