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