Mercurial > projects > ldc
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 /****************************************************************************************/ |