1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | #include "CGCleanup.h" |
20 | #include "CodeGenFunction.h" |
21 | #include "llvm/Support/SaveAndRestore.h" |
22 | |
23 | using namespace clang; |
24 | using namespace CodeGen; |
25 | |
26 | bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) { |
27 | if (rv.isScalar()) |
28 | return DominatingLLVMValue::needsSaving(rv.getScalarVal()); |
29 | if (rv.isAggregate()) |
30 | return DominatingLLVMValue::needsSaving(rv.getAggregatePointer()); |
31 | return true; |
32 | } |
33 | |
34 | DominatingValue<RValue>::saved_type |
35 | DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) { |
36 | if (rv.isScalar()) { |
37 | llvm::Value *V = rv.getScalarVal(); |
38 | |
39 | |
40 | if (!DominatingLLVMValue::needsSaving(V)) |
41 | return saved_type(V, ScalarLiteral); |
42 | |
43 | |
44 | Address addr = |
45 | CGF.CreateDefaultAlignTempAlloca(V->getType(), "saved-rvalue"); |
46 | CGF.Builder.CreateStore(V, addr); |
47 | return saved_type(addr.getPointer(), ScalarAddress); |
48 | } |
49 | |
50 | if (rv.isComplex()) { |
51 | CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); |
52 | llvm::Type *ComplexTy = |
53 | llvm::StructType::get(V.first->getType(), V.second->getType()); |
54 | Address addr = CGF.CreateDefaultAlignTempAlloca(ComplexTy, "saved-complex"); |
55 | CGF.Builder.CreateStore(V.first, CGF.Builder.CreateStructGEP(addr, 0)); |
56 | CGF.Builder.CreateStore(V.second, CGF.Builder.CreateStructGEP(addr, 1)); |
57 | return saved_type(addr.getPointer(), ComplexAddress); |
58 | } |
59 | |
60 | assert(rv.isAggregate()); |
61 | Address V = rv.getAggregateAddress(); |
62 | if (!DominatingLLVMValue::needsSaving(V.getPointer())) |
63 | return saved_type(V.getPointer(), AggregateLiteral, |
64 | V.getAlignment().getQuantity()); |
65 | |
66 | Address addr = |
67 | CGF.CreateTempAlloca(V.getType(), CGF.getPointerAlign(), "saved-rvalue"); |
68 | CGF.Builder.CreateStore(V.getPointer(), addr); |
69 | return saved_type(addr.getPointer(), AggregateAddress, |
70 | V.getAlignment().getQuantity()); |
71 | } |
72 | |
73 | |
74 | |
75 | |
76 | RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) { |
77 | auto getSavingAddress = [&](llvm::Value *value) { |
78 | auto alignment = cast<llvm::AllocaInst>(value)->getAlignment(); |
79 | return Address(value, CharUnits::fromQuantity(alignment)); |
80 | }; |
81 | switch (K) { |
82 | case ScalarLiteral: |
83 | return RValue::get(Value); |
84 | case ScalarAddress: |
85 | return RValue::get(CGF.Builder.CreateLoad(getSavingAddress(Value))); |
86 | case AggregateLiteral: |
87 | return RValue::getAggregate(Address(Value, CharUnits::fromQuantity(Align))); |
88 | case AggregateAddress: { |
89 | auto addr = CGF.Builder.CreateLoad(getSavingAddress(Value)); |
90 | return RValue::getAggregate(Address(addr, CharUnits::fromQuantity(Align))); |
91 | } |
92 | case ComplexAddress: { |
93 | Address address = getSavingAddress(Value); |
94 | llvm::Value *real = |
95 | CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 0)); |
96 | llvm::Value *imag = |
97 | CGF.Builder.CreateLoad(CGF.Builder.CreateStructGEP(address, 1)); |
98 | return RValue::getComplex(real, imag); |
99 | } |
100 | } |
101 | |
102 | llvm_unreachable("bad saved r-value kind"); |
103 | } |
104 | |
105 | |
106 | char *EHScopeStack::allocate(size_t Size) { |
107 | Size = llvm::alignTo(Size, ScopeStackAlignment); |
108 | if (!StartOfBuffer) { |
109 | unsigned Capacity = 1024; |
110 | while (Capacity < Size) Capacity *= 2; |
111 | StartOfBuffer = new char[Capacity]; |
112 | StartOfData = EndOfBuffer = StartOfBuffer + Capacity; |
113 | } else if (static_cast<size_t>(StartOfData - StartOfBuffer) < Size) { |
114 | unsigned CurrentCapacity = EndOfBuffer - StartOfBuffer; |
115 | unsigned UsedCapacity = CurrentCapacity - (StartOfData - StartOfBuffer); |
116 | |
117 | unsigned NewCapacity = CurrentCapacity; |
118 | do { |
119 | NewCapacity *= 2; |
120 | } while (NewCapacity < UsedCapacity + Size); |
121 | |
122 | char *NewStartOfBuffer = new char[NewCapacity]; |
123 | char *NewEndOfBuffer = NewStartOfBuffer + NewCapacity; |
124 | char *NewStartOfData = NewEndOfBuffer - UsedCapacity; |
125 | memcpy(NewStartOfData, StartOfData, UsedCapacity); |
126 | delete [] StartOfBuffer; |
127 | StartOfBuffer = NewStartOfBuffer; |
128 | EndOfBuffer = NewEndOfBuffer; |
129 | StartOfData = NewStartOfData; |
130 | } |
131 | |
132 | assert(StartOfBuffer + Size <= StartOfData); |
133 | StartOfData -= Size; |
134 | return StartOfData; |
135 | } |
136 | |
137 | void EHScopeStack::deallocate(size_t Size) { |
138 | StartOfData += llvm::alignTo(Size, ScopeStackAlignment); |
139 | } |
140 | |
141 | bool EHScopeStack::containsOnlyLifetimeMarkers( |
142 | EHScopeStack::stable_iterator Old) const { |
143 | for (EHScopeStack::iterator it = begin(); stabilize(it) != Old; it++) { |
144 | EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*it); |
145 | if (!cleanup || !cleanup->isLifetimeMarker()) |
146 | return false; |
147 | } |
148 | |
149 | return true; |
150 | } |
151 | |
152 | bool EHScopeStack::requiresLandingPad() const { |
153 | for (stable_iterator si = getInnermostEHScope(); si != stable_end(); ) { |
154 | |
155 | if (auto *cleanup = dyn_cast<EHCleanupScope>(&*find(si))) |
156 | if (cleanup->isLifetimeMarker()) { |
157 | si = cleanup->getEnclosingEHScope(); |
158 | continue; |
159 | } |
160 | return true; |
161 | } |
162 | |
163 | return false; |
164 | } |
165 | |
166 | EHScopeStack::stable_iterator |
167 | EHScopeStack::getInnermostActiveNormalCleanup() const { |
168 | for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end(); |
169 | si != se; ) { |
170 | EHCleanupScope &cleanup = cast<EHCleanupScope>(*find(si)); |
171 | if (cleanup.isActive()) return si; |
172 | si = cleanup.getEnclosingNormalCleanup(); |
173 | } |
174 | return stable_end(); |
175 | } |
176 | |
177 | |
178 | void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) { |
179 | char *Buffer = allocate(EHCleanupScope::getSizeForCleanupSize(Size)); |
180 | bool IsNormalCleanup = Kind & NormalCleanup; |
181 | bool IsEHCleanup = Kind & EHCleanup; |
182 | bool IsActive = !(Kind & InactiveCleanup); |
183 | bool IsLifetimeMarker = Kind & LifetimeMarker; |
184 | EHCleanupScope *Scope = |
185 | new (Buffer) EHCleanupScope(IsNormalCleanup, |
186 | IsEHCleanup, |
187 | IsActive, |
188 | Size, |
189 | BranchFixups.size(), |
190 | InnermostNormalCleanup, |
191 | InnermostEHScope); |
192 | if (IsNormalCleanup) |
193 | InnermostNormalCleanup = stable_begin(); |
194 | if (IsEHCleanup) |
195 | InnermostEHScope = stable_begin(); |
196 | if (IsLifetimeMarker) |
197 | Scope->setLifetimeMarker(); |
198 | |
199 | return Scope->getCleanupBuffer(); |
200 | } |
201 | |
202 | void EHScopeStack::popCleanup() { |
203 | (0) . __assert_fail ("!empty() && \"popping exception stack when not empty\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 203, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!empty() && "popping exception stack when not empty"); |
204 | |
205 | (*begin())", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 205, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<EHCleanupScope>(*begin())); |
206 | EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin()); |
207 | InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup(); |
208 | InnermostEHScope = Cleanup.getEnclosingEHScope(); |
209 | deallocate(Cleanup.getAllocatedSize()); |
210 | |
211 | |
212 | Cleanup.Destroy(); |
213 | |
214 | |
215 | if (!BranchFixups.empty()) { |
216 | |
217 | |
218 | if (!hasNormalCleanups()) |
219 | BranchFixups.clear(); |
220 | |
221 | |
222 | else |
223 | popNullFixups(); |
224 | } |
225 | } |
226 | |
227 | EHFilterScope *EHScopeStack::pushFilter(unsigned numFilters) { |
228 | assert(getInnermostEHScope() == stable_end()); |
229 | char *buffer = allocate(EHFilterScope::getSizeForNumFilters(numFilters)); |
230 | EHFilterScope *filter = new (buffer) EHFilterScope(numFilters); |
231 | InnermostEHScope = stable_begin(); |
232 | return filter; |
233 | } |
234 | |
235 | void EHScopeStack::popFilter() { |
236 | (0) . __assert_fail ("!empty() && \"popping exception stack when not empty\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 236, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!empty() && "popping exception stack when not empty"); |
237 | |
238 | EHFilterScope &filter = cast<EHFilterScope>(*begin()); |
239 | deallocate(EHFilterScope::getSizeForNumFilters(filter.getNumFilters())); |
240 | |
241 | InnermostEHScope = filter.getEnclosingEHScope(); |
242 | } |
243 | |
244 | EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) { |
245 | char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers)); |
246 | EHCatchScope *scope = |
247 | new (buffer) EHCatchScope(numHandlers, InnermostEHScope); |
248 | InnermostEHScope = stable_begin(); |
249 | return scope; |
250 | } |
251 | |
252 | void EHScopeStack::pushTerminate() { |
253 | char *Buffer = allocate(EHTerminateScope::getSize()); |
254 | new (Buffer) EHTerminateScope(InnermostEHScope); |
255 | InnermostEHScope = stable_begin(); |
256 | } |
257 | |
258 | |
259 | |
260 | |
261 | |
262 | |
263 | void EHScopeStack::popNullFixups() { |
264 | |
265 | |
266 | assert(hasNormalCleanups()); |
267 | |
268 | EHScopeStack::iterator it = find(InnermostNormalCleanup); |
269 | unsigned MinSize = cast<EHCleanupScope>(*it).getFixupDepth(); |
270 | (0) . __assert_fail ("BranchFixups.size() >= MinSize && \"fixup stack out of order\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 270, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BranchFixups.size() >= MinSize && "fixup stack out of order"); |
271 | |
272 | while (BranchFixups.size() > MinSize && |
273 | BranchFixups.back().Destination == nullptr) |
274 | BranchFixups.pop_back(); |
275 | } |
276 | |
277 | Address CodeGenFunction::createCleanupActiveFlag() { |
278 | |
279 | Address active = CreateTempAllocaWithoutCast( |
280 | Builder.getInt1Ty(), CharUnits::One(), "cleanup.cond"); |
281 | |
282 | |
283 | |
284 | setBeforeOutermostConditional(Builder.getFalse(), active); |
285 | |
286 | |
287 | Builder.CreateStore(Builder.getTrue(), active); |
288 | |
289 | return active; |
290 | } |
291 | |
292 | void CodeGenFunction::initFullExprCleanupWithFlag(Address ActiveFlag) { |
293 | |
294 | EHCleanupScope &cleanup = cast<EHCleanupScope>(*EHStack.begin()); |
295 | (0) . __assert_fail ("!cleanup.hasActiveFlag() && \"cleanup already has active flag?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 295, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!cleanup.hasActiveFlag() && "cleanup already has active flag?"); |
296 | cleanup.setActiveFlag(ActiveFlag); |
297 | |
298 | if (cleanup.isNormalCleanup()) cleanup.setTestFlagInNormalCleanup(); |
299 | if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup(); |
300 | } |
301 | |
302 | void EHScopeStack::Cleanup::anchor() {} |
303 | |
304 | static void createStoreInstBefore(llvm::Value *value, Address addr, |
305 | llvm::Instruction *beforeInst) { |
306 | auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); |
307 | store->setAlignment(addr.getAlignment().getQuantity()); |
308 | } |
309 | |
310 | static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, |
311 | llvm::Instruction *beforeInst) { |
312 | auto load = new llvm::LoadInst(addr.getPointer(), name, beforeInst); |
313 | load->setAlignment(addr.getAlignment().getQuantity()); |
314 | return load; |
315 | } |
316 | |
317 | |
318 | |
319 | |
320 | static void ResolveAllBranchFixups(CodeGenFunction &CGF, |
321 | llvm::SwitchInst *Switch, |
322 | llvm::BasicBlock *CleanupEntry) { |
323 | llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded; |
324 | |
325 | for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) { |
326 | |
327 | BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I); |
328 | if (Fixup.Destination == nullptr) continue; |
329 | |
330 | |
331 | |
332 | |
333 | |
334 | |
335 | |
336 | |
337 | |
338 | if (Fixup.OptimisticBranchBlock == nullptr) { |
339 | createStoreInstBefore(CGF.Builder.getInt32(Fixup.DestinationIndex), |
340 | CGF.getNormalCleanupDestSlot(), |
341 | Fixup.InitialBranch); |
342 | Fixup.InitialBranch->setSuccessor(0, CleanupEntry); |
343 | } |
344 | |
345 | |
346 | if (!CasesAdded.insert(Fixup.Destination).second) |
347 | continue; |
348 | |
349 | Switch->addCase(CGF.Builder.getInt32(Fixup.DestinationIndex), |
350 | Fixup.Destination); |
351 | } |
352 | |
353 | CGF.EHStack.clearFixups(); |
354 | } |
355 | |
356 | |
357 | |
358 | static llvm::SwitchInst *TransitionToCleanupSwitch(CodeGenFunction &CGF, |
359 | llvm::BasicBlock *Block) { |
360 | |
361 | |
362 | llvm::Instruction *Term = Block->getTerminator(); |
363 | (0) . __assert_fail ("Term && \"can't transition block without terminator\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 363, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Term && "can't transition block without terminator"); |
364 | |
365 | if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { |
366 | isUnconditional()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 366, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Br->isUnconditional()); |
367 | auto Load = createLoadInstBefore(CGF.getNormalCleanupDestSlot(), |
368 | "cleanup.dest", Term); |
369 | llvm::SwitchInst *Switch = |
370 | llvm::SwitchInst::Create(Load, Br->getSuccessor(0), 4, Block); |
371 | Br->eraseFromParent(); |
372 | return Switch; |
373 | } else { |
374 | return cast<llvm::SwitchInst>(Term); |
375 | } |
376 | } |
377 | |
378 | void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) { |
379 | (0) . __assert_fail ("Block && \"resolving a null target block\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 379, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Block && "resolving a null target block"); |
380 | if (!EHStack.getNumBranchFixups()) return; |
381 | |
382 | (0) . __assert_fail ("EHStack.hasNormalCleanups() && \"branch fixups exist with no normal cleanups on stack\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 383, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(EHStack.hasNormalCleanups() && |
383 | (0) . __assert_fail ("EHStack.hasNormalCleanups() && \"branch fixups exist with no normal cleanups on stack\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 383, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "branch fixups exist with no normal cleanups on stack"); |
384 | |
385 | llvm::SmallPtrSet<llvm::BasicBlock*, 4> ModifiedOptimisticBlocks; |
386 | bool ResolvedAny = false; |
387 | |
388 | for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) { |
389 | |
390 | BranchFixup &Fixup = EHStack.getBranchFixup(I); |
391 | if (Fixup.Destination != Block) continue; |
392 | |
393 | Fixup.Destination = nullptr; |
394 | ResolvedAny = true; |
395 | |
396 | |
397 | |
398 | llvm::BasicBlock *BranchBB = Fixup.OptimisticBranchBlock; |
399 | if (!BranchBB) |
400 | continue; |
401 | |
402 | |
403 | if (!ModifiedOptimisticBlocks.insert(BranchBB).second) |
404 | continue; |
405 | |
406 | llvm::SwitchInst *Switch = TransitionToCleanupSwitch(*this, BranchBB); |
407 | |
408 | |
409 | Switch->addCase(Builder.getInt32(Fixup.DestinationIndex), Block); |
410 | } |
411 | |
412 | if (ResolvedAny) |
413 | EHStack.popNullFixups(); |
414 | } |
415 | |
416 | |
417 | void CodeGenFunction::PopCleanupBlocks( |
418 | EHScopeStack::stable_iterator Old, |
419 | std::initializer_list<llvm::Value **> ValuesToReload) { |
420 | assert(Old.isValid()); |
421 | |
422 | bool HadBranches = false; |
423 | while (EHStack.stable_begin() != Old) { |
424 | EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); |
425 | HadBranches |= Scope.hasBranches(); |
426 | |
427 | |
428 | |
429 | |
430 | bool FallThroughIsBranchThrough = |
431 | Old.strictlyEncloses(Scope.getEnclosingNormalCleanup()); |
432 | |
433 | PopCleanupBlock(FallThroughIsBranchThrough); |
434 | } |
435 | |
436 | |
437 | |
438 | |
439 | if (!HadBranches) |
440 | return; |
441 | |
442 | |
443 | |
444 | for (llvm::Value **ReloadedValue : ValuesToReload) { |
445 | auto *Inst = dyn_cast_or_null<llvm::Instruction>(*ReloadedValue); |
446 | if (!Inst) |
447 | continue; |
448 | |
449 | |
450 | |
451 | auto *AI = dyn_cast<llvm::AllocaInst>(Inst); |
452 | if (AI && AI->isStaticAlloca()) |
453 | continue; |
454 | |
455 | Address Tmp = |
456 | CreateDefaultAlignTempAlloca(Inst->getType(), "tmp.exprcleanup"); |
457 | |
458 | |
459 | llvm::BasicBlock::iterator InsertBefore; |
460 | if (auto *Invoke = dyn_cast<llvm::InvokeInst>(Inst)) |
461 | InsertBefore = Invoke->getNormalDest()->getFirstInsertionPt(); |
462 | else |
463 | InsertBefore = std::next(Inst->getIterator()); |
464 | CGBuilderTy(CGM, &*InsertBefore).CreateStore(Inst, Tmp); |
465 | |
466 | |
467 | *ReloadedValue = Builder.CreateLoad(Tmp); |
468 | } |
469 | } |
470 | |
471 | |
472 | |
473 | void CodeGenFunction::PopCleanupBlocks( |
474 | EHScopeStack::stable_iterator Old, size_t OldLifetimeExtendedSize, |
475 | std::initializer_list<llvm::Value **> ValuesToReload) { |
476 | PopCleanupBlocks(Old, ValuesToReload); |
477 | |
478 | |
479 | for (size_t I = OldLifetimeExtendedSize, |
480 | E = LifetimeExtendedCleanupStack.size(); I != E; ) { |
481 | |
482 | (0) . __assert_fail ("(I % alignof(LifetimeExtendedCleanupHeader) == 0) && \"misaligned cleanup stack entry\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 483, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert((I % alignof(LifetimeExtendedCleanupHeader) == 0) && |
483 | (0) . __assert_fail ("(I % alignof(LifetimeExtendedCleanupHeader) == 0) && \"misaligned cleanup stack entry\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 483, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> "misaligned cleanup stack entry"); |
484 | |
485 | LifetimeExtendedCleanupHeader &Header = |
486 | reinterpret_cast<LifetimeExtendedCleanupHeader&>( |
487 | LifetimeExtendedCleanupStack[I]); |
488 | I += sizeof(Header); |
489 | |
490 | EHStack.pushCopyOfCleanup(Header.getKind(), |
491 | &LifetimeExtendedCleanupStack[I], |
492 | Header.getSize()); |
493 | I += Header.getSize(); |
494 | |
495 | if (Header.isConditional()) { |
496 | Address ActiveFlag = |
497 | reinterpret_cast<Address &>(LifetimeExtendedCleanupStack[I]); |
498 | initFullExprCleanupWithFlag(ActiveFlag); |
499 | I += sizeof(ActiveFlag); |
500 | } |
501 | } |
502 | LifetimeExtendedCleanupStack.resize(OldLifetimeExtendedSize); |
503 | } |
504 | |
505 | static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF, |
506 | EHCleanupScope &Scope) { |
507 | assert(Scope.isNormalCleanup()); |
508 | llvm::BasicBlock *Entry = Scope.getNormalBlock(); |
509 | if (!Entry) { |
510 | Entry = CGF.createBasicBlock("cleanup"); |
511 | Scope.setNormalBlock(Entry); |
512 | } |
513 | return Entry; |
514 | } |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | static llvm::BasicBlock *SimplifyCleanupEntry(CodeGenFunction &CGF, |
522 | llvm::BasicBlock *Entry) { |
523 | llvm::BasicBlock *Pred = Entry->getSinglePredecessor(); |
524 | if (!Pred) return Entry; |
525 | |
526 | llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Pred->getTerminator()); |
527 | if (!Br || Br->isConditional()) return Entry; |
528 | getSuccessor(0) == Entry", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 528, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Br->getSuccessor(0) == Entry); |
529 | |
530 | |
531 | |
532 | |
533 | bool WasInsertBlock = CGF.Builder.GetInsertBlock() == Entry; |
534 | end()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 534, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!WasInsertBlock || CGF.Builder.GetInsertPoint() == Entry->end()); |
535 | |
536 | |
537 | Br->eraseFromParent(); |
538 | |
539 | |
540 | |
541 | Entry->replaceAllUsesWith(Pred); |
542 | |
543 | |
544 | Pred->getInstList().splice(Pred->end(), Entry->getInstList()); |
545 | |
546 | |
547 | Entry->eraseFromParent(); |
548 | |
549 | if (WasInsertBlock) |
550 | CGF.Builder.SetInsertPoint(Pred); |
551 | |
552 | return Pred; |
553 | } |
554 | |
555 | static void EmitCleanup(CodeGenFunction &CGF, |
556 | EHScopeStack::Cleanup *Fn, |
557 | EHScopeStack::Cleanup::Flags flags, |
558 | Address ActiveFlag) { |
559 | |
560 | |
561 | llvm::BasicBlock *ContBB = nullptr; |
562 | if (ActiveFlag.isValid()) { |
563 | ContBB = CGF.createBasicBlock("cleanup.done"); |
564 | llvm::BasicBlock *CleanupBB = CGF.createBasicBlock("cleanup.action"); |
565 | llvm::Value *IsActive |
566 | = CGF.Builder.CreateLoad(ActiveFlag, "cleanup.is_active"); |
567 | CGF.Builder.CreateCondBr(IsActive, CleanupBB, ContBB); |
568 | CGF.EmitBlock(CleanupBB); |
569 | } |
570 | |
571 | |
572 | Fn->Emit(CGF, flags); |
573 | (0) . __assert_fail ("CGF.HaveInsertPoint() && \"cleanup ended with no insertion point?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 573, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CGF.HaveInsertPoint() && "cleanup ended with no insertion point?"); |
574 | |
575 | |
576 | if (ActiveFlag.isValid()) |
577 | CGF.EmitBlock(ContBB); |
578 | } |
579 | |
580 | static void ForwardPrebranchedFallthrough(llvm::BasicBlock *Exit, |
581 | llvm::BasicBlock *From, |
582 | llvm::BasicBlock *To) { |
583 | |
584 | |
585 | llvm::Instruction *Term = Exit->getTerminator(); |
586 | |
587 | if (llvm::BranchInst *Br = dyn_cast<llvm::BranchInst>(Term)) { |
588 | isUnconditional() && Br->getSuccessor(0) == From", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 588, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Br->isUnconditional() && Br->getSuccessor(0) == From); |
589 | Br->setSuccessor(0, To); |
590 | } else { |
591 | llvm::SwitchInst *Switch = cast<llvm::SwitchInst>(Term); |
592 | for (unsigned I = 0, E = Switch->getNumSuccessors(); I != E; ++I) |
593 | if (Switch->getSuccessor(I) == From) |
594 | Switch->setSuccessor(I, To); |
595 | } |
596 | } |
597 | |
598 | |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | static void destroyOptimisticNormalEntry(CodeGenFunction &CGF, |
605 | EHCleanupScope &scope) { |
606 | llvm::BasicBlock *entry = scope.getNormalBlock(); |
607 | if (!entry) return; |
608 | |
609 | |
610 | llvm::BasicBlock *unreachableBB = CGF.getUnreachableBlock(); |
611 | for (llvm::BasicBlock::use_iterator |
612 | i = entry->use_begin(), e = entry->use_end(); i != e; ) { |
613 | llvm::Use &use = *i; |
614 | ++i; |
615 | |
616 | use.set(unreachableBB); |
617 | |
618 | |
619 | llvm::SwitchInst *si = cast<llvm::SwitchInst>(use.getUser()); |
620 | if (si->getNumCases() == 1 && si->getDefaultDest() == unreachableBB) { |
621 | |
622 | llvm::BranchInst::Create(si->case_begin()->getCaseSuccessor(), si); |
623 | |
624 | |
625 | llvm::LoadInst *condition = cast<llvm::LoadInst>(si->getCondition()); |
626 | |
627 | |
628 | si->eraseFromParent(); |
629 | |
630 | |
631 | getOperand(0) == CGF.NormalCleanupDest.getPointer()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 631, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(condition->getOperand(0) == CGF.NormalCleanupDest.getPointer()); |
632 | use_empty()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 632, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(condition->use_empty()); |
633 | condition->eraseFromParent(); |
634 | } |
635 | } |
636 | |
637 | use_empty()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 637, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(entry->use_empty()); |
638 | delete entry; |
639 | } |
640 | |
641 | |
642 | |
643 | |
644 | void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { |
645 | (0) . __assert_fail ("!EHStack.empty() && \"cleanup stack is empty!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 645, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!EHStack.empty() && "cleanup stack is empty!"); |
646 | (0) . __assert_fail ("isa(*EHStack.begin()) && \"top not a cleanup!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 646, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<EHCleanupScope>(*EHStack.begin()) && "top not a cleanup!"); |
647 | EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.begin()); |
648 | assert(Scope.getFixupDepth() <= EHStack.getNumBranchFixups()); |
649 | |
650 | |
651 | bool IsActive = Scope.isActive(); |
652 | Address NormalActiveFlag = |
653 | Scope.shouldTestFlagInNormalCleanup() ? Scope.getActiveFlag() |
654 | : Address::invalid(); |
655 | Address EHActiveFlag = |
656 | Scope.shouldTestFlagInEHCleanup() ? Scope.getActiveFlag() |
657 | : Address::invalid(); |
658 | |
659 | |
660 | |
661 | llvm::BasicBlock *EHEntry = Scope.getCachedEHDispatchBlock(); |
662 | assert(Scope.hasEHBranches() == (EHEntry != nullptr)); |
663 | bool RequiresEHCleanup = (EHEntry != nullptr); |
664 | EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope(); |
665 | |
666 | |
667 | |
668 | |
669 | unsigned FixupDepth = Scope.getFixupDepth(); |
670 | bool HasFixups = EHStack.getNumBranchFixups() != FixupDepth; |
671 | |
672 | |
673 | bool HasExistingBranches = Scope.hasBranches(); |
674 | |
675 | |
676 | llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock(); |
677 | bool HasFallthrough = (FallthroughSource != nullptr && IsActive); |
678 | |
679 | |
680 | |
681 | |
682 | |
683 | bool HasPrebranchedFallthrough = |
684 | (FallthroughSource && FallthroughSource->getTerminator()); |
685 | |
686 | |
687 | |
688 | |
689 | getTerminator()->getSuccessor(0) == Scope.getNormalBlock())", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 692, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Scope.isNormalCleanup() || !HasPrebranchedFallthrough || |
690 | getTerminator()->getSuccessor(0) == Scope.getNormalBlock())", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 692, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> (Scope.getNormalBlock() && |
691 | getTerminator()->getSuccessor(0) == Scope.getNormalBlock())", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 692, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> FallthroughSource->getTerminator()->getSuccessor(0) |
692 | getTerminator()->getSuccessor(0) == Scope.getNormalBlock())", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 692, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> == Scope.getNormalBlock())); |
693 | |
694 | bool RequiresNormalCleanup = false; |
695 | if (Scope.isNormalCleanup() && |
696 | (HasFixups || HasExistingBranches || HasFallthrough)) { |
697 | RequiresNormalCleanup = true; |
698 | } |
699 | |
700 | |
701 | |
702 | if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) { |
703 | llvm::BasicBlock *prebranchDest; |
704 | |
705 | |
706 | |
707 | |
708 | if (FallthroughIsBranchThrough) { |
709 | EHScope &enclosing = *EHStack.find(Scope.getEnclosingNormalCleanup()); |
710 | prebranchDest = CreateNormalEntry(*this, cast<EHCleanupScope>(enclosing)); |
711 | |
712 | |
713 | |
714 | |
715 | |
716 | } else { |
717 | prebranchDest = createBasicBlock("forwarded-prebranch"); |
718 | EmitBlock(prebranchDest); |
719 | } |
720 | |
721 | llvm::BasicBlock *normalEntry = Scope.getNormalBlock(); |
722 | use_empty()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 722, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(normalEntry && !normalEntry->use_empty()); |
723 | |
724 | ForwardPrebranchedFallthrough(FallthroughSource, |
725 | normalEntry, prebranchDest); |
726 | } |
727 | |
728 | |
729 | if (!RequiresNormalCleanup && !RequiresEHCleanup) { |
730 | destroyOptimisticNormalEntry(*this, Scope); |
731 | EHStack.popCleanup(); |
732 | assert(EHStack.getNumBranchFixups() == 0 || |
733 | EHStack.hasNormalCleanups()); |
734 | return; |
735 | } |
736 | |
737 | |
738 | |
739 | |
740 | |
741 | |
742 | auto *CleanupSource = reinterpret_cast<char *>(Scope.getCleanupBuffer()); |
743 | llvm::AlignedCharArray<EHScopeStack::ScopeStackAlignment, 8 * sizeof(void *)> CleanupBufferStack; |
744 | std::unique_ptr<char[]> CleanupBufferHeap; |
745 | size_t CleanupSize = Scope.getCleanupSize(); |
746 | EHScopeStack::Cleanup *Fn; |
747 | |
748 | if (CleanupSize <= sizeof(CleanupBufferStack)) { |
749 | memcpy(CleanupBufferStack.buffer, CleanupSource, CleanupSize); |
750 | Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferStack.buffer); |
751 | } else { |
752 | CleanupBufferHeap.reset(new char[CleanupSize]); |
753 | memcpy(CleanupBufferHeap.get(), CleanupSource, CleanupSize); |
754 | Fn = reinterpret_cast<EHScopeStack::Cleanup *>(CleanupBufferHeap.get()); |
755 | } |
756 | |
757 | EHScopeStack::Cleanup::Flags cleanupFlags; |
758 | if (Scope.isNormalCleanup()) |
759 | cleanupFlags.setIsNormalCleanupKind(); |
760 | if (Scope.isEHCleanup()) |
761 | cleanupFlags.setIsEHCleanupKind(); |
762 | |
763 | if (!RequiresNormalCleanup) { |
764 | destroyOptimisticNormalEntry(*this, Scope); |
765 | EHStack.popCleanup(); |
766 | } else { |
767 | |
768 | |
769 | if (HasFallthrough && !HasPrebranchedFallthrough && |
770 | !HasFixups && !HasExistingBranches) { |
771 | |
772 | destroyOptimisticNormalEntry(*this, Scope); |
773 | EHStack.popCleanup(); |
774 | |
775 | EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); |
776 | |
777 | |
778 | |
779 | } else { |
780 | |
781 | llvm::BasicBlock *NormalEntry = CreateNormalEntry(*this, Scope); |
782 | |
783 | |
784 | |
785 | CGBuilderTy::InsertPoint savedInactiveFallthroughIP; |
786 | |
787 | |
788 | |
789 | if (HasFallthrough) { |
790 | if (!HasPrebranchedFallthrough) |
791 | Builder.CreateStore(Builder.getInt32(0), getNormalCleanupDestSlot()); |
792 | |
793 | |
794 | |
795 | } else if (FallthroughSource) { |
796 | (0) . __assert_fail ("!IsActive && \"source without fallthrough for active cleanup\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 796, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!IsActive && "source without fallthrough for active cleanup"); |
797 | savedInactiveFallthroughIP = Builder.saveAndClearIP(); |
798 | } |
799 | |
800 | |
801 | |
802 | |
803 | EmitBlock(NormalEntry); |
804 | |
805 | |
806 | |
807 | |
808 | bool HasEnclosingCleanups = |
809 | (Scope.getEnclosingNormalCleanup() != EHStack.stable_end()); |
810 | |
811 | |
812 | |
813 | |
814 | |
815 | |
816 | llvm::BasicBlock *BranchThroughDest = nullptr; |
817 | if (Scope.hasBranchThroughs() || |
818 | (FallthroughSource && FallthroughIsBranchThrough) || |
819 | (HasFixups && HasEnclosingCleanups)) { |
820 | assert(HasEnclosingCleanups); |
821 | EHScope &S = *EHStack.find(Scope.getEnclosingNormalCleanup()); |
822 | BranchThroughDest = CreateNormalEntry(*this, cast<EHCleanupScope>(S)); |
823 | } |
824 | |
825 | llvm::BasicBlock *FallthroughDest = nullptr; |
826 | SmallVector<llvm::Instruction*, 2> InstsToAppend; |
827 | |
828 | |
829 | |
830 | if (!Scope.hasBranchThroughs() && !HasFixups && !HasFallthrough && |
831 | Scope.getNumBranchAfters() == 1) { |
832 | assert(!BranchThroughDest || !IsActive); |
833 | |
834 | |
835 | llvm::Instruction *NormalCleanupDestSlot = |
836 | cast<llvm::Instruction>(getNormalCleanupDestSlot().getPointer()); |
837 | if (NormalCleanupDestSlot->hasOneUse()) { |
838 | NormalCleanupDestSlot->user_back()->eraseFromParent(); |
839 | NormalCleanupDestSlot->eraseFromParent(); |
840 | NormalCleanupDest = Address::invalid(); |
841 | } |
842 | |
843 | llvm::BasicBlock *BranchAfter = Scope.getBranchAfterBlock(0); |
844 | InstsToAppend.push_back(llvm::BranchInst::Create(BranchAfter)); |
845 | |
846 | |
847 | |
848 | |
849 | |
850 | |
851 | } else if (Scope.getNumBranchAfters() || |
852 | (HasFallthrough && !FallthroughIsBranchThrough) || |
853 | (HasFixups && !HasEnclosingCleanups)) { |
854 | |
855 | llvm::BasicBlock *Default = |
856 | (BranchThroughDest ? BranchThroughDest : getUnreachableBlock()); |
857 | |
858 | |
859 | const unsigned SwitchCapacity = 10; |
860 | |
861 | llvm::LoadInst *Load = |
862 | createLoadInstBefore(getNormalCleanupDestSlot(), "cleanup.dest", |
863 | nullptr); |
864 | llvm::SwitchInst *Switch = |
865 | llvm::SwitchInst::Create(Load, Default, SwitchCapacity); |
866 | |
867 | InstsToAppend.push_back(Load); |
868 | InstsToAppend.push_back(Switch); |
869 | |
870 | |
871 | if (FallthroughSource && !FallthroughIsBranchThrough) { |
872 | FallthroughDest = createBasicBlock("cleanup.cont"); |
873 | if (HasFallthrough) |
874 | Switch->addCase(Builder.getInt32(0), FallthroughDest); |
875 | } |
876 | |
877 | for (unsigned I = 0, E = Scope.getNumBranchAfters(); I != E; ++I) { |
878 | Switch->addCase(Scope.getBranchAfterIndex(I), |
879 | Scope.getBranchAfterBlock(I)); |
880 | } |
881 | |
882 | |
883 | |
884 | if (HasFixups && !HasEnclosingCleanups) |
885 | ResolveAllBranchFixups(*this, Switch, NormalEntry); |
886 | } else { |
887 | |
888 | assert(BranchThroughDest); |
889 | InstsToAppend.push_back(llvm::BranchInst::Create(BranchThroughDest)); |
890 | } |
891 | |
892 | |
893 | EHStack.popCleanup(); |
894 | assert(EHStack.hasNormalCleanups() == HasEnclosingCleanups); |
895 | |
896 | EmitCleanup(*this, Fn, cleanupFlags, NormalActiveFlag); |
897 | |
898 | |
899 | llvm::BasicBlock *NormalExit = Builder.GetInsertBlock(); |
900 | for (unsigned I = 0, E = InstsToAppend.size(); I != E; ++I) |
901 | NormalExit->getInstList().push_back(InstsToAppend[I]); |
902 | |
903 | |
904 | for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); |
905 | I < E; ++I) { |
906 | BranchFixup &Fixup = EHStack.getBranchFixup(I); |
907 | if (!Fixup.Destination) continue; |
908 | if (!Fixup.OptimisticBranchBlock) { |
909 | createStoreInstBefore(Builder.getInt32(Fixup.DestinationIndex), |
910 | getNormalCleanupDestSlot(), |
911 | Fixup.InitialBranch); |
912 | Fixup.InitialBranch->setSuccessor(0, NormalEntry); |
913 | } |
914 | Fixup.OptimisticBranchBlock = NormalExit; |
915 | } |
916 | |
917 | |
918 | |
919 | |
920 | |
921 | if (!HasFallthrough && FallthroughSource) { |
922 | |
923 | |
924 | |
925 | assert(!IsActive); |
926 | Builder.restoreIP(savedInactiveFallthroughIP); |
927 | |
928 | |
929 | |
930 | |
931 | } else if (HasFallthrough && FallthroughDest) { |
932 | assert(!FallthroughIsBranchThrough); |
933 | EmitBlock(FallthroughDest); |
934 | |
935 | |
936 | |
937 | } else if (HasFallthrough) { |
938 | |
939 | |
940 | |
941 | } else { |
942 | Builder.ClearInsertionPoint(); |
943 | } |
944 | |
945 | |
946 | |
947 | |
948 | |
949 | llvm::BasicBlock *NewNormalEntry = |
950 | SimplifyCleanupEntry(*this, NormalEntry); |
951 | |
952 | |
953 | |
954 | if (NewNormalEntry != NormalEntry && NormalEntry == NormalExit) |
955 | for (unsigned I = FixupDepth, E = EHStack.getNumBranchFixups(); |
956 | I < E; ++I) |
957 | EHStack.getBranchFixup(I).OptimisticBranchBlock = NewNormalEntry; |
958 | } |
959 | } |
960 | |
961 | assert(EHStack.hasNormalCleanups() || EHStack.getNumBranchFixups() == 0); |
962 | |
963 | |
964 | if (RequiresEHCleanup) { |
965 | CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); |
966 | |
967 | EmitBlock(EHEntry); |
968 | |
969 | llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent); |
970 | |
971 | |
972 | |
973 | |
974 | bool PushedTerminate = false; |
975 | SaveAndRestore<llvm::Instruction *> RestoreCurrentFuncletPad( |
976 | CurrentFuncletPad); |
977 | llvm::CleanupPadInst *CPI = nullptr; |
978 | |
979 | const EHPersonality &Personality = EHPersonality::get(*this); |
980 | if (Personality.usesFuncletPads()) { |
981 | llvm::Value *ParentPad = CurrentFuncletPad; |
982 | if (!ParentPad) |
983 | ParentPad = llvm::ConstantTokenNone::get(CGM.getLLVMContext()); |
984 | CurrentFuncletPad = CPI = Builder.CreateCleanupPad(ParentPad); |
985 | } |
986 | |
987 | |
988 | if (!Personality.isMSVCPersonality()) { |
989 | EHStack.pushTerminate(); |
990 | PushedTerminate = true; |
991 | } |
992 | |
993 | |
994 | |
995 | if (EHActiveFlag.isValid() || IsActive) { |
996 | cleanupFlags.setIsForEHCleanup(); |
997 | EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); |
998 | } |
999 | |
1000 | if (CPI) |
1001 | Builder.CreateCleanupRet(CPI, NextAction); |
1002 | else |
1003 | Builder.CreateBr(NextAction); |
1004 | |
1005 | |
1006 | if (PushedTerminate) |
1007 | EHStack.popTerminate(); |
1008 | |
1009 | Builder.restoreIP(SavedIP); |
1010 | |
1011 | SimplifyCleanupEntry(*this, EHEntry); |
1012 | } |
1013 | } |
1014 | |
1015 | |
1016 | |
1017 | |
1018 | bool CodeGenFunction::isObviouslyBranchWithoutCleanups(JumpDest Dest) const { |
1019 | (0) . __assert_fail ("Dest.getScopeDepth().encloses(EHStack.stable_begin()) && \"stale jump destination\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1020, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) |
1020 | (0) . __assert_fail ("Dest.getScopeDepth().encloses(EHStack.stable_begin()) && \"stale jump destination\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1020, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "stale jump destination"); |
1021 | |
1022 | |
1023 | EHScopeStack::stable_iterator TopCleanup = |
1024 | EHStack.getInnermostActiveNormalCleanup(); |
1025 | |
1026 | |
1027 | |
1028 | |
1029 | if (TopCleanup == EHStack.stable_end() || |
1030 | TopCleanup.encloses(Dest.getScopeDepth())) |
1031 | return true; |
1032 | |
1033 | |
1034 | return false; |
1035 | } |
1036 | |
1037 | |
1038 | |
1039 | |
1040 | |
1041 | |
1042 | |
1043 | void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) { |
1044 | (0) . __assert_fail ("Dest.getScopeDepth().encloses(EHStack.stable_begin()) && \"stale jump destination\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1045, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Dest.getScopeDepth().encloses(EHStack.stable_begin()) |
1045 | (0) . __assert_fail ("Dest.getScopeDepth().encloses(EHStack.stable_begin()) && \"stale jump destination\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1045, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true"> && "stale jump destination"); |
1046 | |
1047 | if (!HaveInsertPoint()) |
1048 | return; |
1049 | |
1050 | |
1051 | llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock()); |
1052 | |
1053 | |
1054 | EHScopeStack::stable_iterator |
1055 | TopCleanup = EHStack.getInnermostActiveNormalCleanup(); |
1056 | |
1057 | |
1058 | |
1059 | |
1060 | if (TopCleanup == EHStack.stable_end() || |
1061 | TopCleanup.encloses(Dest.getScopeDepth())) { |
1062 | Builder.ClearInsertionPoint(); |
1063 | return; |
1064 | } |
1065 | |
1066 | |
1067 | |
1068 | if (!Dest.getScopeDepth().isValid()) { |
1069 | BranchFixup &Fixup = EHStack.addBranchFixup(); |
1070 | Fixup.Destination = Dest.getBlock(); |
1071 | Fixup.DestinationIndex = Dest.getDestIndex(); |
1072 | Fixup.InitialBranch = BI; |
1073 | Fixup.OptimisticBranchBlock = nullptr; |
1074 | |
1075 | Builder.ClearInsertionPoint(); |
1076 | return; |
1077 | } |
1078 | |
1079 | |
1080 | |
1081 | |
1082 | llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex()); |
1083 | createStoreInstBefore(Index, getNormalCleanupDestSlot(), BI); |
1084 | |
1085 | |
1086 | { |
1087 | EHCleanupScope &Scope = |
1088 | cast<EHCleanupScope>(*EHStack.find(TopCleanup)); |
1089 | BI->setSuccessor(0, CreateNormalEntry(*this, Scope)); |
1090 | } |
1091 | |
1092 | |
1093 | EHScopeStack::stable_iterator I = TopCleanup; |
1094 | EHScopeStack::stable_iterator E = Dest.getScopeDepth(); |
1095 | if (E.strictlyEncloses(I)) { |
1096 | while (true) { |
1097 | EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I)); |
1098 | assert(Scope.isNormalCleanup()); |
1099 | I = Scope.getEnclosingNormalCleanup(); |
1100 | |
1101 | |
1102 | |
1103 | if (!E.strictlyEncloses(I)) { |
1104 | Scope.addBranchAfter(Index, Dest.getBlock()); |
1105 | break; |
1106 | } |
1107 | |
1108 | |
1109 | |
1110 | |
1111 | if (!Scope.addBranchThrough(Dest.getBlock())) |
1112 | break; |
1113 | } |
1114 | } |
1115 | |
1116 | Builder.ClearInsertionPoint(); |
1117 | } |
1118 | |
1119 | static bool IsUsedAsNormalCleanup(EHScopeStack &EHStack, |
1120 | EHScopeStack::stable_iterator C) { |
1121 | |
1122 | if (cast<EHCleanupScope>(*EHStack.find(C)).getNormalBlock()) |
1123 | return true; |
1124 | |
1125 | |
1126 | for (EHScopeStack::stable_iterator |
1127 | I = EHStack.getInnermostNormalCleanup(); |
1128 | I != C; ) { |
1129 | assert(C.strictlyEncloses(I)); |
1130 | EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I)); |
1131 | if (S.getNormalBlock()) return true; |
1132 | I = S.getEnclosingNormalCleanup(); |
1133 | } |
1134 | |
1135 | return false; |
1136 | } |
1137 | |
1138 | static bool IsUsedAsEHCleanup(EHScopeStack &EHStack, |
1139 | EHScopeStack::stable_iterator cleanup) { |
1140 | |
1141 | if (EHStack.find(cleanup)->hasEHBranches()) |
1142 | return true; |
1143 | |
1144 | |
1145 | for (EHScopeStack::stable_iterator |
1146 | i = EHStack.getInnermostEHScope(); i != cleanup; ) { |
1147 | assert(cleanup.strictlyEncloses(i)); |
1148 | |
1149 | EHScope &scope = *EHStack.find(i); |
1150 | if (scope.hasEHBranches()) |
1151 | return true; |
1152 | |
1153 | i = scope.getEnclosingEHScope(); |
1154 | } |
1155 | |
1156 | return false; |
1157 | } |
1158 | |
1159 | enum ForActivation_t { |
1160 | ForActivation, |
1161 | ForDeactivation |
1162 | }; |
1163 | |
1164 | |
1165 | |
1166 | |
1167 | |
1168 | |
1169 | static void SetupCleanupBlockActivation(CodeGenFunction &CGF, |
1170 | EHScopeStack::stable_iterator C, |
1171 | ForActivation_t kind, |
1172 | llvm::Instruction *dominatingIP) { |
1173 | EHCleanupScope &Scope = cast<EHCleanupScope>(*CGF.EHStack.find(C)); |
1174 | |
1175 | |
1176 | |
1177 | |
1178 | bool isActivatedInConditional = |
1179 | (kind == ForActivation && CGF.isInConditionalBranch()); |
1180 | |
1181 | bool needFlag = false; |
1182 | |
1183 | |
1184 | |
1185 | |
1186 | if (Scope.isNormalCleanup() && |
1187 | (isActivatedInConditional || IsUsedAsNormalCleanup(CGF.EHStack, C))) { |
1188 | Scope.setTestFlagInNormalCleanup(); |
1189 | needFlag = true; |
1190 | } |
1191 | |
1192 | |
1193 | if (Scope.isEHCleanup() && |
1194 | (isActivatedInConditional || IsUsedAsEHCleanup(CGF.EHStack, C))) { |
1195 | Scope.setTestFlagInEHCleanup(); |
1196 | needFlag = true; |
1197 | } |
1198 | |
1199 | |
1200 | if (!needFlag) return; |
1201 | |
1202 | Address var = Scope.getActiveFlag(); |
1203 | if (!var.isValid()) { |
1204 | var = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), CharUnits::One(), |
1205 | "cleanup.isactive"); |
1206 | Scope.setActiveFlag(var); |
1207 | |
1208 | (0) . __assert_fail ("dominatingIP && \"no existing variable and no dominating IP!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1208, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(dominatingIP && "no existing variable and no dominating IP!"); |
1209 | |
1210 | |
1211 | |
1212 | llvm::Constant *value = CGF.Builder.getInt1(kind == ForDeactivation); |
1213 | |
1214 | |
1215 | |
1216 | if (CGF.isInConditionalBranch()) { |
1217 | CGF.setBeforeOutermostConditional(value, var); |
1218 | } else { |
1219 | createStoreInstBefore(value, var, dominatingIP); |
1220 | } |
1221 | } |
1222 | |
1223 | CGF.Builder.CreateStore(CGF.Builder.getInt1(kind == ForActivation), var); |
1224 | } |
1225 | |
1226 | |
1227 | void CodeGenFunction::ActivateCleanupBlock(EHScopeStack::stable_iterator C, |
1228 | llvm::Instruction *dominatingIP) { |
1229 | (0) . __assert_fail ("C != EHStack.stable_end() && \"activating bottom of stack?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1229, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(C != EHStack.stable_end() && "activating bottom of stack?"); |
1230 | EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); |
1231 | (0) . __assert_fail ("!Scope.isActive() && \"double activation\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1231, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Scope.isActive() && "double activation"); |
1232 | |
1233 | SetupCleanupBlockActivation(*this, C, ForActivation, dominatingIP); |
1234 | |
1235 | Scope.setActive(true); |
1236 | } |
1237 | |
1238 | |
1239 | void CodeGenFunction::DeactivateCleanupBlock(EHScopeStack::stable_iterator C, |
1240 | llvm::Instruction *dominatingIP) { |
1241 | (0) . __assert_fail ("C != EHStack.stable_end() && \"deactivating bottom of stack?\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1241, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(C != EHStack.stable_end() && "deactivating bottom of stack?"); |
1242 | EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(C)); |
1243 | (0) . __assert_fail ("Scope.isActive() && \"double deactivation\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGCleanup.cpp", 1243, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Scope.isActive() && "double deactivation"); |
1244 | |
1245 | |
1246 | |
1247 | if (C == EHStack.stable_begin() && |
1248 | CurrentCleanupScopeDepth.strictlyEncloses(C)) { |
1249 | |
1250 | |
1251 | CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); |
1252 | PopCleanupBlock(); |
1253 | Builder.restoreIP(SavedIP); |
1254 | return; |
1255 | } |
1256 | |
1257 | |
1258 | SetupCleanupBlockActivation(*this, C, ForDeactivation, dominatingIP); |
1259 | |
1260 | Scope.setActive(false); |
1261 | } |
1262 | |
1263 | Address CodeGenFunction::getNormalCleanupDestSlot() { |
1264 | if (!NormalCleanupDest.isValid()) |
1265 | NormalCleanupDest = |
1266 | CreateDefaultAlignTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot"); |
1267 | return NormalCleanupDest; |
1268 | } |
1269 | |
1270 | |
1271 | void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, |
1272 | QualType TempType, |
1273 | Address Ptr) { |
1274 | pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, |
1275 | true); |
1276 | } |
1277 | |