1 | //===- SjLjEHPrepare.cpp - Eliminate Invoke & Unwind instructions ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This transformation is designed for use by code generators which use SjLj |
10 | // based exception handling. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/CodeGen/SjLjEHPrepare.h" |
15 | #include "llvm/ADT/SetVector.h" |
16 | #include "llvm/ADT/SmallPtrSet.h" |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ADT/Statistic.h" |
19 | #include "llvm/CodeGen/Passes.h" |
20 | #include "llvm/IR/Constants.h" |
21 | #include "llvm/IR/DataLayout.h" |
22 | #include "llvm/IR/DerivedTypes.h" |
23 | #include "llvm/IR/IRBuilder.h" |
24 | #include "llvm/IR/Instructions.h" |
25 | #include "llvm/IR/Intrinsics.h" |
26 | #include "llvm/IR/Module.h" |
27 | #include "llvm/InitializePasses.h" |
28 | #include "llvm/Pass.h" |
29 | #include "llvm/Support/Debug.h" |
30 | #include "llvm/Support/raw_ostream.h" |
31 | #include "llvm/Target/TargetMachine.h" |
32 | #include "llvm/Transforms/Utils/Local.h" |
33 | using namespace llvm; |
34 | |
35 | #define DEBUG_TYPE "sjlj-eh-prepare" |
36 | |
37 | STATISTIC(NumInvokes, "Number of invokes replaced" ); |
38 | STATISTIC(NumSpilled, "Number of registers live across unwind edges" ); |
39 | |
40 | namespace { |
41 | class SjLjEHPrepareImpl { |
42 | IntegerType *DataTy = nullptr; |
43 | Type *doubleUnderDataTy = nullptr; |
44 | Type *doubleUnderJBufTy = nullptr; |
45 | Type *FunctionContextTy = nullptr; |
46 | FunctionCallee RegisterFn; |
47 | FunctionCallee UnregisterFn; |
48 | Function *BuiltinSetupDispatchFn = nullptr; |
49 | Function *FrameAddrFn = nullptr; |
50 | Function *StackAddrFn = nullptr; |
51 | Function *StackRestoreFn = nullptr; |
52 | Function *LSDAAddrFn = nullptr; |
53 | Function *CallSiteFn = nullptr; |
54 | Function *FuncCtxFn = nullptr; |
55 | AllocaInst *FuncCtx = nullptr; |
56 | const TargetMachine *TM = nullptr; |
57 | |
58 | public: |
59 | explicit SjLjEHPrepareImpl(const TargetMachine *TM = nullptr) : TM(TM) {} |
60 | bool doInitialization(Module &M); |
61 | bool runOnFunction(Function &F); |
62 | |
63 | private: |
64 | bool setupEntryBlockAndCallSites(Function &F); |
65 | void substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, Value *SelVal); |
66 | Value *setupFunctionContext(Function &F, ArrayRef<LandingPadInst *> LPads); |
67 | void lowerIncomingArguments(Function &F); |
68 | void lowerAcrossUnwindEdges(Function &F, ArrayRef<InvokeInst *> Invokes); |
69 | void insertCallSiteStore(Instruction *I, int Number); |
70 | }; |
71 | |
72 | class SjLjEHPrepare : public FunctionPass { |
73 | SjLjEHPrepareImpl Impl; |
74 | |
75 | public: |
76 | static char ID; // Pass identification, replacement for typeid |
77 | explicit SjLjEHPrepare(const TargetMachine *TM = nullptr) |
78 | : FunctionPass(ID), Impl(TM) {} |
79 | bool doInitialization(Module &M) override { return Impl.doInitialization(M); } |
80 | bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); }; |
81 | |
82 | StringRef getPassName() const override { |
83 | return "SJLJ Exception Handling preparation" ; |
84 | } |
85 | }; |
86 | |
87 | } // end anonymous namespace |
88 | |
89 | PreservedAnalyses SjLjEHPreparePass::run(Function &F, |
90 | FunctionAnalysisManager &FAM) { |
91 | SjLjEHPrepareImpl Impl(TM); |
92 | Impl.doInitialization(M&: *F.getParent()); |
93 | bool Changed = Impl.runOnFunction(F); |
94 | return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); |
95 | } |
96 | |
97 | char SjLjEHPrepare::ID = 0; |
98 | INITIALIZE_PASS(SjLjEHPrepare, DEBUG_TYPE, "Prepare SjLj exceptions" , |
99 | false, false) |
100 | |
101 | // Public Interface To the SjLjEHPrepare pass. |
102 | FunctionPass *llvm::createSjLjEHPreparePass(const TargetMachine *TM) { |
103 | return new SjLjEHPrepare(TM); |
104 | } |
105 | |
106 | // doInitialization - Set up decalarations and types needed to process |
107 | // exceptions. |
108 | bool SjLjEHPrepareImpl::doInitialization(Module &M) { |
109 | // Build the function context structure. |
110 | // builtin_setjmp uses a five word jbuf |
111 | Type *VoidPtrTy = PointerType::getUnqual(C&: M.getContext()); |
112 | unsigned DataBits = |
113 | TM ? TM->getSjLjDataSize() : TargetMachine::DefaultSjLjDataSize; |
114 | DataTy = Type::getIntNTy(C&: M.getContext(), N: DataBits); |
115 | doubleUnderDataTy = ArrayType::get(ElementType: DataTy, NumElements: 4); |
116 | doubleUnderJBufTy = ArrayType::get(ElementType: VoidPtrTy, NumElements: 5); |
117 | FunctionContextTy = StructType::get(elt1: VoidPtrTy, // __prev |
118 | elts: DataTy, // call_site |
119 | elts: doubleUnderDataTy, // __data |
120 | elts: VoidPtrTy, // __personality |
121 | elts: VoidPtrTy, // __lsda |
122 | elts: doubleUnderJBufTy // __jbuf |
123 | ); |
124 | |
125 | return false; |
126 | } |
127 | |
128 | /// insertCallSiteStore - Insert a store of the call-site value to the |
129 | /// function context |
130 | void SjLjEHPrepareImpl::insertCallSiteStore(Instruction *I, int Number) { |
131 | IRBuilder<> Builder(I); |
132 | |
133 | // Get a reference to the call_site field. |
134 | Type *Int32Ty = Type::getInt32Ty(C&: I->getContext()); |
135 | Value *Zero = ConstantInt::get(Ty: Int32Ty, V: 0); |
136 | Value *One = ConstantInt::get(Ty: Int32Ty, V: 1); |
137 | Value *Idxs[2] = { Zero, One }; |
138 | Value *CallSite = |
139 | Builder.CreateGEP(Ty: FunctionContextTy, Ptr: FuncCtx, IdxList: Idxs, Name: "call_site" ); |
140 | |
141 | // Insert a store of the call-site number |
142 | ConstantInt *CallSiteNoC = ConstantInt::get(Ty: DataTy, V: Number); |
143 | Builder.CreateStore(Val: CallSiteNoC, Ptr: CallSite, isVolatile: true /*volatile*/); |
144 | } |
145 | |
146 | /// MarkBlocksLiveIn - Insert BB and all of its predecessors into LiveBBs until |
147 | /// we reach blocks we've already seen. |
148 | static void MarkBlocksLiveIn(BasicBlock *BB, |
149 | SmallPtrSetImpl<BasicBlock *> &LiveBBs) { |
150 | if (!LiveBBs.insert(Ptr: BB).second) |
151 | return; // already been here. |
152 | |
153 | for (BasicBlock *B : inverse_depth_first(G: BB)) |
154 | LiveBBs.insert(Ptr: B); |
155 | } |
156 | |
157 | /// substituteLPadValues - Substitute the values returned by the landingpad |
158 | /// instruction with those returned by the personality function. |
159 | void SjLjEHPrepareImpl::substituteLPadValues(LandingPadInst *LPI, Value *ExnVal, |
160 | Value *SelVal) { |
161 | SmallVector<Value *, 8> UseWorkList(LPI->users()); |
162 | while (!UseWorkList.empty()) { |
163 | Value *Val = UseWorkList.pop_back_val(); |
164 | auto *EVI = dyn_cast<ExtractValueInst>(Val); |
165 | if (!EVI) |
166 | continue; |
167 | if (EVI->getNumIndices() != 1) |
168 | continue; |
169 | if (*EVI->idx_begin() == 0) |
170 | EVI->replaceAllUsesWith(V: ExnVal); |
171 | else if (*EVI->idx_begin() == 1) |
172 | EVI->replaceAllUsesWith(V: SelVal); |
173 | if (EVI->use_empty()) |
174 | EVI->eraseFromParent(); |
175 | } |
176 | |
177 | if (LPI->use_empty()) |
178 | return; |
179 | |
180 | // There are still some uses of LPI. Construct an aggregate with the exception |
181 | // values and replace the LPI with that aggregate. |
182 | Type *LPadType = LPI->getType(); |
183 | Value *LPadVal = PoisonValue::get(T: LPadType); |
184 | auto *SelI = cast<Instruction>(Val: SelVal); |
185 | IRBuilder<> Builder(SelI->getParent(), std::next(x: SelI->getIterator())); |
186 | LPadVal = Builder.CreateInsertValue(Agg: LPadVal, Val: ExnVal, Idxs: 0, Name: "lpad.val" ); |
187 | LPadVal = Builder.CreateInsertValue(Agg: LPadVal, Val: SelVal, Idxs: 1, Name: "lpad.val" ); |
188 | |
189 | LPI->replaceAllUsesWith(V: LPadVal); |
190 | } |
191 | |
192 | /// setupFunctionContext - Allocate the function context on the stack and fill |
193 | /// it with all of the data that we know at this point. |
194 | Value * |
195 | SjLjEHPrepareImpl::setupFunctionContext(Function &F, |
196 | ArrayRef<LandingPadInst *> LPads) { |
197 | BasicBlock *EntryBB = &F.front(); |
198 | |
199 | // Create an alloca for the incoming jump buffer ptr and the new jump buffer |
200 | // that needs to be restored on all exits from the function. This is an alloca |
201 | // because the value needs to be added to the global context list. |
202 | auto &DL = F.getDataLayout(); |
203 | const Align Alignment = DL.getPrefTypeAlign(Ty: FunctionContextTy); |
204 | FuncCtx = new AllocaInst(FunctionContextTy, DL.getAllocaAddrSpace(), nullptr, |
205 | Alignment, "fn_context" , EntryBB->begin()); |
206 | |
207 | // Fill in the function context structure. |
208 | for (LandingPadInst *LPI : LPads) { |
209 | IRBuilder<> Builder(LPI->getParent(), |
210 | LPI->getParent()->getFirstInsertionPt()); |
211 | |
212 | // Reference the __data field. |
213 | Value *FCData = |
214 | Builder.CreateConstGEP2_32(Ty: FunctionContextTy, Ptr: FuncCtx, Idx0: 0, Idx1: 2, Name: "__data" ); |
215 | |
216 | // The exception values come back in context->__data[0]. |
217 | Value *ExceptionAddr = Builder.CreateConstGEP2_32(Ty: doubleUnderDataTy, Ptr: FCData, |
218 | Idx0: 0, Idx1: 0, Name: "exception_gep" ); |
219 | Value *ExnVal = Builder.CreateLoad(Ty: DataTy, Ptr: ExceptionAddr, isVolatile: true, Name: "exn_val" ); |
220 | ExnVal = Builder.CreateIntToPtr(V: ExnVal, DestTy: Builder.getPtrTy()); |
221 | |
222 | Value *SelectorAddr = Builder.CreateConstGEP2_32(Ty: doubleUnderDataTy, Ptr: FCData, |
223 | Idx0: 0, Idx1: 1, Name: "exn_selector_gep" ); |
224 | Value *SelVal = |
225 | Builder.CreateLoad(Ty: DataTy, Ptr: SelectorAddr, isVolatile: true, Name: "exn_selector_val" ); |
226 | |
227 | // SelVal must be Int32Ty, so trunc it |
228 | SelVal = Builder.CreateTrunc(V: SelVal, DestTy: Type::getInt32Ty(C&: F.getContext())); |
229 | |
230 | substituteLPadValues(LPI, ExnVal, SelVal); |
231 | } |
232 | |
233 | // Personality function |
234 | IRBuilder<> Builder(EntryBB->getTerminator()); |
235 | Value *PersonalityFn = F.getPersonalityFn(); |
236 | Value *PersonalityFieldPtr = Builder.CreateConstGEP2_32( |
237 | Ty: FunctionContextTy, Ptr: FuncCtx, Idx0: 0, Idx1: 3, Name: "pers_fn_gep" ); |
238 | Builder.CreateStore(Val: PersonalityFn, Ptr: PersonalityFieldPtr, /*isVolatile=*/true); |
239 | |
240 | // LSDA address |
241 | Value *LSDA = Builder.CreateCall(Callee: LSDAAddrFn, Args: {}, Name: "lsda_addr" ); |
242 | Value *LSDAFieldPtr = |
243 | Builder.CreateConstGEP2_32(Ty: FunctionContextTy, Ptr: FuncCtx, Idx0: 0, Idx1: 4, Name: "lsda_gep" ); |
244 | Builder.CreateStore(Val: LSDA, Ptr: LSDAFieldPtr, /*isVolatile=*/true); |
245 | |
246 | return FuncCtx; |
247 | } |
248 | |
249 | /// lowerIncomingArguments - To avoid having to handle incoming arguments |
250 | /// specially, we lower each arg to a copy instruction in the entry block. This |
251 | /// ensures that the argument value itself cannot be live out of the entry |
252 | /// block. |
253 | void SjLjEHPrepareImpl::lowerIncomingArguments(Function &F) { |
254 | BasicBlock::iterator AfterAllocaInsPt = F.begin()->begin(); |
255 | while (isa<AllocaInst>(Val: AfterAllocaInsPt) && |
256 | cast<AllocaInst>(Val&: AfterAllocaInsPt)->isStaticAlloca()) |
257 | ++AfterAllocaInsPt; |
258 | assert(AfterAllocaInsPt != F.front().end()); |
259 | |
260 | for (auto &AI : F.args()) { |
261 | // Swift error really is a register that we model as memory -- instruction |
262 | // selection will perform mem-to-reg for us and spill/reload appropriately |
263 | // around calls that clobber it. There is no need to spill this |
264 | // value to the stack and doing so would not be allowed. |
265 | if (AI.isSwiftError()) |
266 | continue; |
267 | |
268 | Type *Ty = AI.getType(); |
269 | |
270 | // Use 'select i8 true, %arg, undef' to simulate a 'no-op' instruction. |
271 | Value *TrueValue = ConstantInt::getTrue(Context&: F.getContext()); |
272 | Value *UndefValue = UndefValue::get(T: Ty); |
273 | Instruction *SI = SelectInst::Create( |
274 | C: TrueValue, S1: &AI, S2: UndefValue, NameStr: AI.getName() + ".tmp" , InsertBefore: AfterAllocaInsPt); |
275 | AI.replaceAllUsesWith(V: SI); |
276 | |
277 | // Reset the operand, because it was clobbered by the RAUW above. |
278 | SI->setOperand(i: 1, Val: &AI); |
279 | } |
280 | } |
281 | |
282 | /// lowerAcrossUnwindEdges - Find all variables which are alive across an unwind |
283 | /// edge and spill them. |
284 | void SjLjEHPrepareImpl::lowerAcrossUnwindEdges(Function &F, |
285 | ArrayRef<InvokeInst *> Invokes) { |
286 | // Finally, scan the code looking for instructions with bad live ranges. |
287 | for (BasicBlock &BB : F) { |
288 | for (Instruction &Inst : BB) { |
289 | // Ignore obvious cases we don't have to handle. In particular, most |
290 | // instructions either have no uses or only have a single use inside the |
291 | // current block. Ignore them quickly. |
292 | if (Inst.use_empty()) |
293 | continue; |
294 | if (Inst.hasOneUse() && |
295 | cast<Instruction>(Val: Inst.user_back())->getParent() == &BB && |
296 | !isa<PHINode>(Val: Inst.user_back())) |
297 | continue; |
298 | |
299 | // If this is an alloca in the entry block, it's not a real register |
300 | // value. |
301 | if (auto *AI = dyn_cast<AllocaInst>(Val: &Inst)) |
302 | if (AI->isStaticAlloca()) |
303 | continue; |
304 | |
305 | // Avoid iterator invalidation by copying users to a temporary vector. |
306 | SmallVector<Instruction *, 16> Users; |
307 | for (User *U : Inst.users()) { |
308 | Instruction *UI = cast<Instruction>(Val: U); |
309 | if (UI->getParent() != &BB || isa<PHINode>(Val: UI)) |
310 | Users.push_back(Elt: UI); |
311 | } |
312 | |
313 | // Find all of the blocks that this value is live in. |
314 | SmallPtrSet<BasicBlock *, 32> LiveBBs; |
315 | LiveBBs.insert(Ptr: &BB); |
316 | while (!Users.empty()) { |
317 | Instruction *U = Users.pop_back_val(); |
318 | |
319 | if (!isa<PHINode>(Val: U)) { |
320 | MarkBlocksLiveIn(BB: U->getParent(), LiveBBs); |
321 | } else { |
322 | // Uses for a PHI node occur in their predecessor block. |
323 | PHINode *PN = cast<PHINode>(Val: U); |
324 | for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) |
325 | if (PN->getIncomingValue(i) == &Inst) |
326 | MarkBlocksLiveIn(BB: PN->getIncomingBlock(i), LiveBBs); |
327 | } |
328 | } |
329 | |
330 | // Now that we know all of the blocks that this thing is live in, see if |
331 | // it includes any of the unwind locations. |
332 | bool NeedsSpill = false; |
333 | for (InvokeInst *Invoke : Invokes) { |
334 | BasicBlock *UnwindBlock = Invoke->getUnwindDest(); |
335 | if (UnwindBlock != &BB && LiveBBs.count(Ptr: UnwindBlock)) { |
336 | LLVM_DEBUG(dbgs() << "SJLJ Spill: " << Inst << " around " |
337 | << UnwindBlock->getName() << "\n" ); |
338 | NeedsSpill = true; |
339 | break; |
340 | } |
341 | } |
342 | |
343 | // If we decided we need a spill, do it. |
344 | // FIXME: Spilling this way is overkill, as it forces all uses of |
345 | // the value to be reloaded from the stack slot, even those that aren't |
346 | // in the unwind blocks. We should be more selective. |
347 | if (NeedsSpill) { |
348 | DemoteRegToStack(X&: Inst, VolatileLoads: true); |
349 | ++NumSpilled; |
350 | } |
351 | } |
352 | } |
353 | |
354 | // Go through the landing pads and remove any PHIs there. |
355 | for (InvokeInst *Invoke : Invokes) { |
356 | BasicBlock *UnwindBlock = Invoke->getUnwindDest(); |
357 | LandingPadInst *LPI = UnwindBlock->getLandingPadInst(); |
358 | |
359 | // Place PHIs into a set to avoid invalidating the iterator. |
360 | SmallPtrSet<PHINode *, 8> PHIsToDemote; |
361 | for (BasicBlock::iterator PN = UnwindBlock->begin(); isa<PHINode>(Val: PN); ++PN) |
362 | PHIsToDemote.insert(Ptr: cast<PHINode>(Val&: PN)); |
363 | if (PHIsToDemote.empty()) |
364 | continue; |
365 | |
366 | // Demote the PHIs to the stack. |
367 | for (PHINode *PN : PHIsToDemote) |
368 | DemotePHIToStack(P: PN); |
369 | |
370 | // Move the landingpad instruction back to the top of the landing pad block. |
371 | LPI->moveBefore(MovePos: &UnwindBlock->front()); |
372 | } |
373 | } |
374 | |
375 | /// setupEntryBlockAndCallSites - Setup the entry block by creating and filling |
376 | /// the function context and marking the call sites with the appropriate |
377 | /// values. These values are used by the DWARF EH emitter. |
378 | bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) { |
379 | SmallVector<ReturnInst *, 16> Returns; |
380 | SmallVector<InvokeInst *, 16> Invokes; |
381 | SmallSetVector<LandingPadInst *, 16> LPads; |
382 | |
383 | // Look through the terminators of the basic blocks to find invokes. |
384 | for (BasicBlock &BB : F) |
385 | if (auto *II = dyn_cast<InvokeInst>(Val: BB.getTerminator())) { |
386 | if (Function *Callee = II->getCalledFunction()) |
387 | if (Callee->getIntrinsicID() == Intrinsic::donothing) { |
388 | // Remove the NOP invoke. |
389 | BranchInst::Create(IfTrue: II->getNormalDest(), InsertBefore: II->getIterator()); |
390 | II->eraseFromParent(); |
391 | continue; |
392 | } |
393 | |
394 | Invokes.push_back(Elt: II); |
395 | LPads.insert(X: II->getUnwindDest()->getLandingPadInst()); |
396 | } else if (auto *RI = dyn_cast<ReturnInst>(Val: BB.getTerminator())) { |
397 | Returns.push_back(Elt: RI); |
398 | } |
399 | |
400 | if (Invokes.empty()) |
401 | return false; |
402 | |
403 | NumInvokes += Invokes.size(); |
404 | |
405 | lowerIncomingArguments(F); |
406 | lowerAcrossUnwindEdges(F, Invokes); |
407 | |
408 | Value *FuncCtx = |
409 | setupFunctionContext(F, LPads: ArrayRef(LPads.begin(), LPads.end())); |
410 | BasicBlock *EntryBB = &F.front(); |
411 | IRBuilder<> Builder(EntryBB->getTerminator()); |
412 | |
413 | // Get a reference to the jump buffer. |
414 | Value *JBufPtr = |
415 | Builder.CreateConstGEP2_32(Ty: FunctionContextTy, Ptr: FuncCtx, Idx0: 0, Idx1: 5, Name: "jbuf_gep" ); |
416 | |
417 | // Save the frame pointer. |
418 | Value *FramePtr = Builder.CreateConstGEP2_32(Ty: doubleUnderJBufTy, Ptr: JBufPtr, Idx0: 0, Idx1: 0, |
419 | Name: "jbuf_fp_gep" ); |
420 | |
421 | Value *Val = Builder.CreateCall(Callee: FrameAddrFn, Args: Builder.getInt32(C: 0), Name: "fp" ); |
422 | Builder.CreateStore(Val, Ptr: FramePtr, /*isVolatile=*/true); |
423 | |
424 | // Save the stack pointer. |
425 | Value *StackPtr = Builder.CreateConstGEP2_32(Ty: doubleUnderJBufTy, Ptr: JBufPtr, Idx0: 0, Idx1: 2, |
426 | Name: "jbuf_sp_gep" ); |
427 | |
428 | Val = Builder.CreateCall(Callee: StackAddrFn, Args: {}, Name: "sp" ); |
429 | Builder.CreateStore(Val, Ptr: StackPtr, /*isVolatile=*/true); |
430 | |
431 | // Call the setup_dispatch intrinsic. It fills in the rest of the jmpbuf. |
432 | Builder.CreateCall(Callee: BuiltinSetupDispatchFn, Args: {}); |
433 | |
434 | // Store a pointer to the function context so that the back-end will know |
435 | // where to look for it. |
436 | Builder.CreateCall(Callee: FuncCtxFn, Args: FuncCtx); |
437 | |
438 | // At this point, we are all set up, update the invoke instructions to mark |
439 | // their call_site values. |
440 | for (unsigned I = 0, E = Invokes.size(); I != E; ++I) { |
441 | insertCallSiteStore(I: Invokes[I], Number: I + 1); |
442 | |
443 | ConstantInt *CallSiteNum = |
444 | ConstantInt::get(Ty: Type::getInt32Ty(C&: F.getContext()), V: I + 1); |
445 | |
446 | // Record the call site value for the back end so it stays associated with |
447 | // the invoke. |
448 | CallInst::Create(Func: CallSiteFn, Args: CallSiteNum, NameStr: "" , InsertBefore: Invokes[I]->getIterator()); |
449 | } |
450 | |
451 | // Mark call instructions that aren't nounwind as no-action (call_site == |
452 | // -1). Skip the entry block, as prior to then, no function context has been |
453 | // created for this function and any unexpected exceptions thrown will go |
454 | // directly to the caller's context, which is what we want anyway, so no need |
455 | // to do anything here. |
456 | for (BasicBlock &BB : F) { |
457 | if (&BB == &F.front()) |
458 | continue; |
459 | for (Instruction &I : BB) |
460 | if (I.mayThrow()) |
461 | insertCallSiteStore(I: &I, Number: -1); |
462 | } |
463 | |
464 | // Register the function context and make sure it's known to not throw |
465 | CallInst *Register = CallInst::Create( |
466 | Func: RegisterFn, Args: FuncCtx, NameStr: "" , InsertBefore: EntryBB->getTerminator()->getIterator()); |
467 | Register->setDoesNotThrow(); |
468 | |
469 | // Following any allocas not in the entry block, update the saved SP in the |
470 | // jmpbuf to the new value. |
471 | for (BasicBlock &BB : F) { |
472 | if (&BB == &F.front()) |
473 | continue; |
474 | for (Instruction &I : BB) { |
475 | if (auto *CI = dyn_cast<CallInst>(Val: &I)) { |
476 | if (CI->getCalledFunction() != StackRestoreFn) |
477 | continue; |
478 | } else if (!isa<AllocaInst>(Val: &I)) { |
479 | continue; |
480 | } |
481 | Instruction *StackAddr = CallInst::Create(Func: StackAddrFn, NameStr: "sp" ); |
482 | StackAddr->insertAfter(InsertPos: &I); |
483 | new StoreInst(StackAddr, StackPtr, true, |
484 | std::next(x: StackAddr->getIterator())); |
485 | } |
486 | } |
487 | |
488 | // Finally, for any returns from this function, if this function contains an |
489 | // invoke, add a call to unregister the function context. |
490 | for (ReturnInst *Return : Returns) { |
491 | Instruction *InsertPoint = Return; |
492 | if (CallInst *CI = Return->getParent()->getTerminatingMustTailCall()) |
493 | InsertPoint = CI; |
494 | CallInst::Create(Func: UnregisterFn, Args: FuncCtx, NameStr: "" , InsertBefore: InsertPoint->getIterator()); |
495 | } |
496 | |
497 | return true; |
498 | } |
499 | |
500 | bool SjLjEHPrepareImpl::runOnFunction(Function &F) { |
501 | Module &M = *F.getParent(); |
502 | RegisterFn = M.getOrInsertFunction( |
503 | Name: "_Unwind_SjLj_Register" , RetTy: Type::getVoidTy(C&: M.getContext()), |
504 | Args: PointerType::getUnqual(ElementType: FunctionContextTy)); |
505 | UnregisterFn = M.getOrInsertFunction( |
506 | Name: "_Unwind_SjLj_Unregister" , RetTy: Type::getVoidTy(C&: M.getContext()), |
507 | Args: PointerType::getUnqual(ElementType: FunctionContextTy)); |
508 | |
509 | PointerType *AllocaPtrTy = M.getDataLayout().getAllocaPtrType(Ctx&: M.getContext()); |
510 | |
511 | FrameAddrFn = |
512 | Intrinsic::getDeclaration(M: &M, id: Intrinsic::frameaddress, Tys: {AllocaPtrTy}); |
513 | StackAddrFn = |
514 | Intrinsic::getDeclaration(M: &M, id: Intrinsic::stacksave, Tys: {AllocaPtrTy}); |
515 | StackRestoreFn = |
516 | Intrinsic::getDeclaration(M: &M, id: Intrinsic::stackrestore, Tys: {AllocaPtrTy}); |
517 | BuiltinSetupDispatchFn = |
518 | Intrinsic::getDeclaration(M: &M, id: Intrinsic::eh_sjlj_setup_dispatch); |
519 | LSDAAddrFn = Intrinsic::getDeclaration(M: &M, id: Intrinsic::eh_sjlj_lsda); |
520 | CallSiteFn = Intrinsic::getDeclaration(M: &M, id: Intrinsic::eh_sjlj_callsite); |
521 | FuncCtxFn = Intrinsic::getDeclaration(M: &M, id: Intrinsic::eh_sjlj_functioncontext); |
522 | |
523 | bool Res = setupEntryBlockAndCallSites(F); |
524 | return Res; |
525 | } |
526 | |