comparison gen/llvmhelpers.cpp @ 1141:f99a3b393c03

Reorganize EnclosingHandlers to require less changes to the frontend and allow us to implement the synchronized storage class for functions.
author Christian Kamm <kamm incasoftware de>
date Tue, 24 Mar 2009 21:18:18 +0100
parents a08983bf972e
children 40caa8207b3e
comparison
equal deleted inserted replaced
1137:45d73f0a9b43 1141:f99a3b393c03
108 /****************************************************************************************/ 108 /****************************************************************************************/
109 /*//////////////////////////////////////////////////////////////////////////////////////// 109 /*////////////////////////////////////////////////////////////////////////////////////////
110 // ASSERT HELPER 110 // ASSERT HELPER
111 ////////////////////////////////////////////////////////////////////////////////////////*/ 111 ////////////////////////////////////////////////////////////////////////////////////////*/
112 112
113 void DtoAssert(Module* M, Loc* loc, DValue* msg) 113 void DtoAssert(Module* M, Loc loc, DValue* msg)
114 { 114 {
115 std::vector<LLValue*> args; 115 std::vector<LLValue*> args;
116 116
117 // func 117 // func
118 const char* fname = msg ? "_d_assert_msg" : "_d_assert"; 118 const char* fname = msg ? "_d_assert_msg" : "_d_assert";
131 M->ir.irModule = new IrModule(M, M->srcfile->toChars()); 131 M->ir.irModule = new IrModule(M, M->srcfile->toChars());
132 132
133 args.push_back(DtoLoad(M->ir.irModule->fileName)); 133 args.push_back(DtoLoad(M->ir.irModule->fileName));
134 134
135 // line param 135 // line param
136 LLConstant* c = DtoConstUint(loc->linnum); 136 LLConstant* c = DtoConstUint(loc.linnum);
137 args.push_back(c); 137 args.push_back(c);
138 138
139 // call 139 // call
140 gIR->CreateCallOrInvoke(fn, args.begin(), args.end()); 140 gIR->CreateCallOrInvoke(fn, args.begin(), args.end());
141 141
170 170
171 /****************************************************************************************/ 171 /****************************************************************************************/
172 /*//////////////////////////////////////////////////////////////////////////////////////// 172 /*////////////////////////////////////////////////////////////////////////////////////////
173 // GOTO HELPER 173 // GOTO HELPER
174 ////////////////////////////////////////////////////////////////////////////////////////*/ 174 ////////////////////////////////////////////////////////////////////////////////////////*/
175 void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler, TryFinallyStatement* sourcetf) 175 void DtoGoto(Loc loc, Identifier* target)
176 { 176 {
177 assert(!gIR->scopereturned()); 177 assert(!gIR->scopereturned());
178 178
179 LabelStatement* lblstmt = DtoLabelStatement(target); 179 LabelStatement* lblstmt = DtoLabelStatement(target);
180 if(!lblstmt) { 180 if(!lblstmt) {
181 error(*loc, "the label %s does not exist", target->toChars()); 181 error(loc, "the label %s does not exist", target->toChars());
182 fatal(); 182 fatal();
183 } 183 }
184 184
185 // if the target label is inside inline asm, error 185 // if the target label is inside inline asm, error
186 if(lblstmt->asmLabel) { 186 if(lblstmt->asmLabel) {
187 error(*loc, "cannot goto to label %s inside an inline asm block", target->toChars()); 187 error(loc, "cannot goto to label %s inside an inline asm block", target->toChars());
188 fatal(); 188 fatal();
189 } 189 }
190 190
191 // find target basic block 191 // find target basic block
192 std::string labelname = gIR->func()->getScopedLabelName(target->toChars()); 192 std::string labelname = gIR->func()->getScopedLabelName(target->toChars());
193 llvm::BasicBlock*& targetBB = gIR->func()->labelToBB[labelname]; 193 llvm::BasicBlock*& targetBB = gIR->func()->labelToBB[labelname];
194 if (targetBB == NULL) 194 if (targetBB == NULL)
195 targetBB = llvm::BasicBlock::Create("label_" + labelname, gIR->topfunc()); 195 targetBB = llvm::BasicBlock::Create("label_" + labelname, gIR->topfunc());
196 196
197 // find finallys between goto and label 197 // emit code for finallys between goto and label
198 EnclosingHandler* endfinally = enclosinghandler; 198 DtoEnclosingHandlers(loc, lblstmt);
199 while(endfinally != NULL && endfinally != lblstmt->enclosinghandler) {
200 endfinally = endfinally->getEnclosing();
201 }
202
203 // error if didn't find tf statement of label
204 if(endfinally != lblstmt->enclosinghandler)
205 error(*loc, "cannot goto into try block");
206 199
207 // goto into finally blocks is forbidden by the spec 200 // goto into finally blocks is forbidden by the spec
208 // though it should not be problematic to implement 201 // but should work fine
202 /*
209 if(lblstmt->tf != sourcetf) { 203 if(lblstmt->tf != sourcetf) {
210 error(*loc, "spec disallows goto into finally block"); 204 error(loc, "spec disallows goto into finally block");
211 fatal(); 205 fatal();
212 } 206 }*/
213
214 // emit code for finallys between goto and label
215 DtoEnclosingHandlers(enclosinghandler, endfinally);
216 207
217 llvm::BranchInst::Create(targetBB, gIR->scopebb()); 208 llvm::BranchInst::Create(targetBB, gIR->scopebb());
218 } 209 }
219 210
220 /****************************************************************************************/ 211 /****************************************************************************************/
223 ////////////////////////////////////////////////////////////////////////////////////////*/ 214 ////////////////////////////////////////////////////////////////////////////////////////*/
224 215
225 void EnclosingSynchro::emitCode(IRState * p) 216 void EnclosingSynchro::emitCode(IRState * p)
226 { 217 {
227 if (s->exp) 218 if (s->exp)
228 DtoLeaveMonitor(s->llsync); 219 DtoLeaveMonitor(s->exp->toElem(p)->getRVal());
229 else 220 else
230 DtoLeaveCritical(s->llsync); 221 DtoLeaveCritical(s->llsync);
231 } 222 }
232 223
233 EnclosingHandler* EnclosingSynchro::getEnclosing()
234 {
235 return s->enclosinghandler;
236 }
237
238 //////////////////////////////////////////////////////////////////////////////////////// 224 ////////////////////////////////////////////////////////////////////////////////////////
239 225
240 void EnclosingVolatile::emitCode(IRState * p) 226 void EnclosingVolatile::emitCode(IRState * p)
241 { 227 {
242 // store-load barrier 228 // store-load barrier
243 DtoMemoryBarrier(false, false, true, false); 229 DtoMemoryBarrier(false, false, true, false);
244 } 230 }
245 231
246 EnclosingHandler* EnclosingVolatile::getEnclosing()
247 {
248 return v->enclosinghandler;
249 }
250
251 //////////////////////////////////////////////////////////////////////////////////////// 232 ////////////////////////////////////////////////////////////////////////////////////////
252 233
253 void EnclosingTryFinally::emitCode(IRState * p) 234 void EnclosingTryFinally::emitCode(IRState * p)
254 { 235 {
255 if (tf->finalbody) 236 if (tf->finalbody)
256 tf->finalbody->toIR(p); 237 tf->finalbody->toIR(p);
257 } 238 }
258 239
259 EnclosingHandler* EnclosingTryFinally::getEnclosing()
260 {
261 return tf->enclosinghandler;
262 }
263
264 //////////////////////////////////////////////////////////////////////////////////////// 240 ////////////////////////////////////////////////////////////////////////////////////////
265 241
266 void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end) 242 void DtoEnclosingHandlers(Loc loc, Statement* target)
267 { 243 {
268 // verify that end encloses start 244 // labels are a special case: they are not required to enclose the current scope
269 EnclosingHandler* endfinally = start; 245 // for them we use the enclosing scope handler as a reference point
270 while(endfinally != NULL && endfinally != end) { 246 LabelStatement* lblstmt = dynamic_cast<LabelStatement*>(target);
271 endfinally = endfinally->getEnclosing(); 247 if (lblstmt)
272 } 248 target = lblstmt->enclosingScopeExit;
273 assert(endfinally == end); 249
274 250 // figure out up until what handler we need to emit
251 IRState::TargetScopeVec::reverse_iterator targetit;
252 for (targetit = gIR->targetScopes.rbegin(); targetit != gIR->targetScopes.rend(); ++targetit) {
253 if (targetit->s == target) {
254 break;
255 }
256 }
257
258 if (target && targetit == gIR->targetScopes.rend()) {
259 if (lblstmt)
260 error(loc, "cannot goto into try, volatile or synchronized statement at %s", target->loc.toChars());
261 else
262 error(loc, "internal error, cannot find jump path to statement at %s", target->loc.toChars());
263 return;
264 }
275 265
276 // 266 //
277 // emit code for finallys between start and end 267 // emit code for enclosing handlers
278 // 268 //
279 269
280 // since the labelstatements possibly inside are private 270 // since the labelstatements possibly inside are private
281 // and might already exist push a label scope 271 // and might already exist push a label scope
282 gIR->func()->pushUniqueLabelScope("enclosing"); 272 gIR->func()->pushUniqueLabelScope("enclosing");
283 EnclosingHandler* tf = start; 273 IRState::TargetScopeVec::reverse_iterator it;
284 while(tf != end) { 274 for (it = gIR->targetScopes.rbegin(); it != targetit; ++it) {
285 tf->emitCode(gIR); 275 if (it->enclosinghandler)
286 tf = tf->getEnclosing(); 276 it->enclosinghandler->emitCode(gIR);
287 } 277 }
288 gIR->func()->popLabelScope(); 278 gIR->func()->popLabelScope();
289 } 279 }
290 280
291 /****************************************************************************************/ 281 /****************************************************************************************/