clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name WinException.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/CodeGen/AsmPrinter -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/CodeGen/AsmPrinter -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/CodeGen/AsmPrinter -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/CodeGen/AsmPrinter -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "WinException.h" |
14 | #include "llvm/ADT/Twine.h" |
15 | #include "llvm/BinaryFormat/COFF.h" |
16 | #include "llvm/BinaryFormat/Dwarf.h" |
17 | #include "llvm/CodeGen/AsmPrinter.h" |
18 | #include "llvm/CodeGen/MachineFrameInfo.h" |
19 | #include "llvm/CodeGen/MachineFunction.h" |
20 | #include "llvm/CodeGen/MachineModuleInfo.h" |
21 | #include "llvm/CodeGen/TargetFrameLowering.h" |
22 | #include "llvm/CodeGen/TargetLowering.h" |
23 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
24 | #include "llvm/CodeGen/WinEHFuncInfo.h" |
25 | #include "llvm/IR/DataLayout.h" |
26 | #include "llvm/IR/Mangler.h" |
27 | #include "llvm/IR/Module.h" |
28 | #include "llvm/MC/MCAsmInfo.h" |
29 | #include "llvm/MC/MCContext.h" |
30 | #include "llvm/MC/MCExpr.h" |
31 | #include "llvm/MC/MCSection.h" |
32 | #include "llvm/MC/MCStreamer.h" |
33 | #include "llvm/MC/MCSymbol.h" |
34 | #include "llvm/Support/ErrorHandling.h" |
35 | #include "llvm/Support/FormattedStream.h" |
36 | #include "llvm/Target/TargetLoweringObjectFile.h" |
37 | #include "llvm/Target/TargetMachine.h" |
38 | #include "llvm/Target/TargetOptions.h" |
39 | using namespace llvm; |
40 | |
41 | WinException::WinException(AsmPrinter *A) : EHStreamer(A) { |
42 | |
43 | |
44 | useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64); |
45 | isAArch64 = Asm->TM.getTargetTriple().isAArch64(); |
46 | isThumb = Asm->TM.getTargetTriple().isThumb(); |
47 | } |
48 | |
49 | WinException::~WinException() {} |
50 | |
51 | |
52 | |
53 | void WinException::endModule() { |
54 | auto &OS = *Asm->OutStreamer; |
55 | const Module *M = MMI->getModule(); |
56 | for (const Function &F : *M) |
57 | if (F.hasFnAttribute("safeseh")) |
58 | OS.EmitCOFFSafeSEH(Asm->getSymbol(&F)); |
59 | |
60 | if (M->getModuleFlag("ehcontguard") && !EHContTargets.empty()) { |
61 | |
62 | OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGEHContSection()); |
63 | for (const MCSymbol *S : EHContTargets) { |
64 | OS.EmitCOFFSymbolIndex(S); |
65 | } |
66 | } |
67 | } |
68 | |
69 | void WinException::beginFunction(const MachineFunction *MF) { |
70 | shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; |
71 | |
72 | |
73 | bool hasLandingPads = !MF->getLandingPads().empty(); |
74 | bool hasEHFunclets = MF->hasEHFunclets(); |
75 | |
76 | const Function &F = MF->getFunction(); |
77 | |
78 | shouldEmitMoves = Asm->needsSEHMoves() && MF->hasWinCFI(); |
79 | |
80 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
81 | unsigned PerEncoding = TLOF.getPersonalityEncoding(); |
82 | |
83 | EHPersonality Per = EHPersonality::Unknown; |
84 | const Function *PerFn = nullptr; |
85 | if (F.hasPersonalityFn()) { |
86 | PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); |
87 | Per = classifyEHPersonality(PerFn); |
88 | } |
89 | |
90 | bool forceEmitPersonality = F.hasPersonalityFn() && |
91 | !isNoOpWithoutInvoke(Per) && |
92 | F.needsUnwindTableEntry(); |
93 | |
94 | shouldEmitPersonality = |
95 | forceEmitPersonality || ((hasLandingPads || hasEHFunclets) && |
96 | PerEncoding != dwarf::DW_EH_PE_omit && PerFn); |
97 | |
98 | unsigned LSDAEncoding = TLOF.getLSDAEncoding(); |
99 | shouldEmitLSDA = shouldEmitPersonality && |
100 | LSDAEncoding != dwarf::DW_EH_PE_omit; |
101 | |
102 | |
103 | |
104 | if (!Asm->MAI->usesWindowsCFI()) { |
105 | if (Per == EHPersonality::MSVC_X86SEH && !hasEHFunclets) { |
106 | |
107 | |
108 | |
109 | const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); |
110 | StringRef FLinkageName = |
111 | GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); |
112 | emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName); |
113 | } |
114 | shouldEmitLSDA = hasEHFunclets; |
115 | shouldEmitPersonality = false; |
116 | return; |
117 | } |
118 | |
119 | beginFunclet(MF->front(), Asm->CurrentFnSym); |
120 | } |
121 | |
122 | void WinException::markFunctionEnd() { |
123 | if (isAArch64 && CurrentFuncletEntry && |
124 | (shouldEmitMoves || shouldEmitPersonality)) |
125 | Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd(); |
126 | } |
127 | |
128 | |
129 | |
130 | void WinException::endFunction(const MachineFunction *MF) { |
131 | if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA) |
| 1 | Assuming field 'shouldEmitPersonality' is true | |
|
132 | return; |
133 | |
134 | const Function &F = MF->getFunction(); |
135 | EHPersonality Per = EHPersonality::Unknown; |
136 | if (F.hasPersonalityFn()) |
| 2 | | Assuming the condition is true | |
|
| |
137 | Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts()); |
138 | |
139 | |
140 | |
141 | |
142 | if (!isFuncletEHPersonality(Per)) { |
| |
143 | MachineFunction *NonConstMF = const_cast<MachineFunction*>(MF); |
144 | NonConstMF->tidyLandingPads(); |
145 | } |
146 | |
147 | endFuncletImpl(); |
148 | |
149 | |
150 | if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets()) |
151 | return; |
152 | |
153 | if (shouldEmitPersonality || shouldEmitLSDA) { |
154 | Asm->OutStreamer->PushSection(); |
155 | |
156 | |
157 | MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection( |
158 | Asm->OutStreamer->getCurrentSectionOnly()); |
159 | Asm->OutStreamer->SwitchSection(XData); |
160 | |
161 | |
162 | |
163 | if (Per == EHPersonality::MSVC_TableSEH) |
| |
164 | emitCSpecificHandlerTable(MF); |
165 | else if (Per == EHPersonality::MSVC_X86SEH) |
| |
166 | emitExceptHandlerTable(MF); |
167 | else if (Per == EHPersonality::MSVC_CXX) |
| |
168 | emitCXXFrameHandler3Table(MF); |
169 | else if (Per == EHPersonality::CoreCLR) |
| |
170 | emitCLRExceptionTable(MF); |
| 9 | | Calling 'WinException::emitCLRExceptionTable' | |
|
171 | else |
172 | emitExceptionTable(); |
173 | |
174 | Asm->OutStreamer->PopSection(); |
175 | } |
176 | |
177 | if (!MF->getCatchretTargets().empty()) { |
178 | |
179 | EHContTargets.insert(EHContTargets.end(), MF->getCatchretTargets().begin(), |
180 | MF->getCatchretTargets().end()); |
181 | } |
182 | } |
183 | |
184 | |
185 | static MCSymbol *getMCSymbolForMBB(AsmPrinter *Asm, |
186 | const MachineBasicBlock *MBB) { |
187 | if (!MBB) |
188 | return nullptr; |
189 | |
190 | assert(MBB->isEHFuncletEntry()); |
191 | |
192 | |
193 | |
194 | const MachineFunction *MF = MBB->getParent(); |
195 | const Function &F = MF->getFunction(); |
196 | StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName()); |
197 | MCContext &Ctx = MF->getContext(); |
198 | StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? "dtor" : "catch"; |
199 | return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" + |
200 | Twine(MBB->getNumber()) + "@?0?" + |
201 | FuncLinkageName + "@4HA"); |
202 | } |
203 | |
204 | void WinException::beginFunclet(const MachineBasicBlock &MBB, |
205 | MCSymbol *Sym) { |
206 | CurrentFuncletEntry = &MBB; |
207 | |
208 | const Function &F = Asm->MF->getFunction(); |
209 | |
210 | if (!Sym) { |
211 | Sym = getMCSymbolForMBB(Asm, &MBB); |
212 | |
213 | |
214 | Asm->OutStreamer->BeginCOFFSymbolDef(Sym); |
215 | Asm->OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC); |
216 | Asm->OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION |
217 | << COFF::SCT_COMPLEX_TYPE_SHIFT); |
218 | Asm->OutStreamer->EndCOFFSymbolDef(); |
219 | |
220 | |
221 | |
222 | Asm->emitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()), |
223 | &F); |
224 | |
225 | |
226 | Asm->OutStreamer->emitLabel(Sym); |
227 | } |
228 | |
229 | |
230 | if (shouldEmitMoves || shouldEmitPersonality) { |
231 | CurrentFuncletTextSection = Asm->OutStreamer->getCurrentSectionOnly(); |
232 | Asm->OutStreamer->EmitWinCFIStartProc(Sym); |
233 | } |
234 | |
235 | if (shouldEmitPersonality) { |
236 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
237 | const Function *PerFn = nullptr; |
238 | |
239 | |
240 | if (F.hasPersonalityFn()) |
241 | PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts()); |
242 | const MCSymbol *PersHandlerSym = |
243 | TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI); |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | if (!CurrentFuncletEntry->isCleanupFuncletEntry()) |
251 | Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true); |
252 | } |
253 | } |
254 | |
255 | void WinException::endFunclet() { |
256 | if (isAArch64 && CurrentFuncletEntry && |
257 | (shouldEmitMoves || shouldEmitPersonality)) { |
258 | Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection); |
259 | Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd(); |
260 | } |
261 | endFuncletImpl(); |
262 | } |
263 | |
264 | void WinException::endFuncletImpl() { |
265 | |
266 | if (!CurrentFuncletEntry) |
267 | return; |
268 | |
269 | const MachineFunction *MF = Asm->MF; |
270 | if (shouldEmitMoves || shouldEmitPersonality) { |
271 | const Function &F = MF->getFunction(); |
272 | EHPersonality Per = EHPersonality::Unknown; |
273 | if (F.hasPersonalityFn()) |
274 | Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts()); |
275 | |
276 | if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality && |
277 | !CurrentFuncletEntry->isCleanupFuncletEntry()) { |
278 | |
279 | Asm->OutStreamer->EmitWinEHHandlerData(); |
280 | |
281 | |
282 | |
283 | StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName()); |
284 | MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol( |
285 | Twine("$cppxdata$", FuncLinkageName)); |
286 | Asm->OutStreamer->emitValue(create32bitRef(FuncInfoXData), 4); |
287 | } else if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets() && |
288 | !CurrentFuncletEntry->isEHFuncletEntry()) { |
289 | |
290 | Asm->OutStreamer->EmitWinEHHandlerData(); |
291 | |
292 | |
293 | |
294 | emitCSpecificHandlerTable(MF); |
295 | } else if (shouldEmitPersonality || shouldEmitLSDA) { |
296 | |
297 | Asm->OutStreamer->EmitWinEHHandlerData(); |
298 | |
299 | |
300 | |
301 | } else { |
302 | |
303 | |
304 | |
305 | } |
306 | |
307 | |
308 | |
309 | |
310 | Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection); |
311 | Asm->OutStreamer->EmitWinCFIEndProc(); |
312 | } |
313 | |
314 | |
315 | CurrentFuncletEntry = nullptr; |
316 | } |
317 | |
318 | const MCExpr *WinException::create32bitRef(const MCSymbol *Value) { |
319 | if (!Value) |
320 | return MCConstantExpr::create(0, Asm->OutContext); |
321 | return MCSymbolRefExpr::create(Value, useImageRel32 |
322 | ? MCSymbolRefExpr::VK_COFF_IMGREL32 |
323 | : MCSymbolRefExpr::VK_None, |
324 | Asm->OutContext); |
325 | } |
326 | |
327 | const MCExpr *WinException::create32bitRef(const GlobalValue *GV) { |
328 | if (!GV) |
329 | return MCConstantExpr::create(0, Asm->OutContext); |
330 | return create32bitRef(Asm->getSymbol(GV)); |
331 | } |
332 | |
333 | const MCExpr *WinException::getLabel(const MCSymbol *Label) { |
334 | return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32, |
335 | Asm->OutContext); |
336 | } |
337 | |
338 | const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) { |
339 | return MCBinaryExpr::createAdd(getLabel(Label), |
340 | MCConstantExpr::create(1, Asm->OutContext), |
341 | Asm->OutContext); |
342 | } |
343 | |
344 | const MCExpr *WinException::getOffset(const MCSymbol *OffsetOf, |
345 | const MCSymbol *OffsetFrom) { |
346 | return MCBinaryExpr::createSub( |
347 | MCSymbolRefExpr::create(OffsetOf, Asm->OutContext), |
348 | MCSymbolRefExpr::create(OffsetFrom, Asm->OutContext), Asm->OutContext); |
349 | } |
350 | |
351 | const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf, |
352 | const MCSymbol *OffsetFrom) { |
353 | return MCBinaryExpr::createAdd(getOffset(OffsetOf, OffsetFrom), |
354 | MCConstantExpr::create(1, Asm->OutContext), |
355 | Asm->OutContext); |
356 | } |
357 | |
358 | int WinException::getFrameIndexOffset(int FrameIndex, |
359 | const WinEHFuncInfo &FuncInfo) { |
360 | const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering(); |
361 | Register UnusedReg; |
362 | if (Asm->MAI->usesWindowsCFI()) { |
363 | StackOffset Offset = |
364 | TFI.getFrameIndexReferencePreferSP(*Asm->MF, FrameIndex, UnusedReg, |
365 | true); |
366 | assert(UnusedReg == |
367 | Asm->MF->getSubtarget() |
368 | .getTargetLowering() |
369 | ->getStackPointerRegisterToSaveRestore()); |
370 | return Offset.getFixed(); |
371 | } |
372 | |
373 | |
374 | |
375 | assert(FuncInfo.EHRegNodeEndOffset != INT_MAX); |
376 | StackOffset Offset = TFI.getFrameIndexReference(*Asm->MF, FrameIndex, UnusedReg); |
377 | Offset += StackOffset::getFixed(FuncInfo.EHRegNodeEndOffset); |
378 | assert(!Offset.getScalable() && |
379 | "Frame offsets with a scalable component are not supported"); |
380 | return Offset.getFixed(); |
381 | } |
382 | |
383 | namespace { |
384 | |
385 | |
386 | const int NullState = -1; |
387 | |
388 | struct InvokeStateChange { |
389 | |
390 | |
391 | const MCSymbol *PreviousEndLabel; |
392 | |
393 | |
394 | |
395 | const MCSymbol *NewStartLabel; |
396 | |
397 | |
398 | |
399 | int NewState; |
400 | }; |
401 | |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | class InvokeStateChangeIterator { |
411 | InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo, |
412 | MachineFunction::const_iterator MFI, |
413 | MachineFunction::const_iterator MFE, |
414 | MachineBasicBlock::const_iterator MBBI, |
415 | int BaseState) |
416 | : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) { |
417 | LastStateChange.PreviousEndLabel = nullptr; |
418 | LastStateChange.NewStartLabel = nullptr; |
419 | LastStateChange.NewState = BaseState; |
420 | scan(); |
421 | } |
422 | |
423 | public: |
424 | static iterator_range<InvokeStateChangeIterator> |
425 | range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin, |
426 | MachineFunction::const_iterator End, int BaseState = NullState) { |
427 | |
428 | |
429 | assert(Begin != End); |
430 | auto BlockBegin = Begin->begin(); |
431 | auto BlockEnd = std::prev(End)->end(); |
432 | return make_range( |
433 | InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState), |
434 | InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState)); |
435 | } |
436 | |
437 | |
438 | bool operator==(const InvokeStateChangeIterator &O) const { |
439 | assert(BaseState == O.BaseState); |
440 | |
441 | if (MFI != O.MFI) |
442 | return false; |
443 | |
444 | if (MBBI != O.MBBI) |
445 | return false; |
446 | |
447 | |
448 | |
449 | |
450 | return CurrentEndLabel == O.CurrentEndLabel; |
451 | } |
452 | |
453 | bool operator!=(const InvokeStateChangeIterator &O) const { |
454 | return !operator==(O); |
455 | } |
456 | InvokeStateChange &operator*() { return LastStateChange; } |
457 | InvokeStateChange *operator->() { return &LastStateChange; } |
458 | InvokeStateChangeIterator &operator++() { return scan(); } |
459 | |
460 | private: |
461 | InvokeStateChangeIterator &scan(); |
462 | |
463 | const WinEHFuncInfo &EHInfo; |
464 | const MCSymbol *CurrentEndLabel = nullptr; |
465 | MachineFunction::const_iterator MFI; |
466 | MachineFunction::const_iterator MFE; |
467 | MachineBasicBlock::const_iterator MBBI; |
468 | InvokeStateChange LastStateChange; |
469 | bool VisitingInvoke = false; |
470 | int BaseState; |
471 | }; |
472 | |
473 | } |
474 | |
475 | InvokeStateChangeIterator &InvokeStateChangeIterator::scan() { |
476 | bool IsNewBlock = false; |
477 | for (; MFI != MFE; ++MFI, IsNewBlock = true) { |
478 | if (IsNewBlock) |
479 | MBBI = MFI->begin(); |
480 | for (auto MBBE = MFI->end(); MBBI != MBBE; ++MBBI) { |
481 | const MachineInstr &MI = *MBBI; |
482 | if (!VisitingInvoke && LastStateChange.NewState != BaseState && |
483 | MI.isCall() && !EHStreamer::callToNoUnwindFunction(&MI)) { |
484 | |
485 | |
486 | |
487 | LastStateChange.PreviousEndLabel = CurrentEndLabel; |
488 | LastStateChange.NewStartLabel = nullptr; |
489 | LastStateChange.NewState = BaseState; |
490 | CurrentEndLabel = nullptr; |
491 | |
492 | ++MBBI; |
493 | return *this; |
494 | } |
495 | |
496 | |
497 | if (!MI.isEHLabel()) |
498 | continue; |
499 | MCSymbol *Label = MI.getOperand(0).getMCSymbol(); |
500 | if (Label == CurrentEndLabel) { |
501 | VisitingInvoke = false; |
502 | continue; |
503 | } |
504 | auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label); |
505 | |
506 | if (InvokeMapIter == EHInfo.LabelToStateMap.end()) |
507 | continue; |
508 | auto &StateAndEnd = InvokeMapIter->second; |
509 | int NewState = StateAndEnd.first; |
510 | |
511 | |
512 | VisitingInvoke = true; |
513 | if (NewState == LastStateChange.NewState) { |
514 | |
515 | |
516 | CurrentEndLabel = StateAndEnd.second; |
517 | continue; |
518 | } |
519 | |
520 | LastStateChange.PreviousEndLabel = CurrentEndLabel; |
521 | LastStateChange.NewStartLabel = Label; |
522 | LastStateChange.NewState = NewState; |
523 | |
524 | CurrentEndLabel = StateAndEnd.second; |
525 | |
526 | ++MBBI; |
527 | return *this; |
528 | } |
529 | } |
530 | |
531 | if (LastStateChange.NewState != BaseState) { |
532 | |
533 | LastStateChange.PreviousEndLabel = CurrentEndLabel; |
534 | LastStateChange.NewStartLabel = nullptr; |
535 | LastStateChange.NewState = BaseState; |
536 | |
537 | assert(CurrentEndLabel != nullptr); |
538 | return *this; |
539 | } |
540 | |
541 | CurrentEndLabel = nullptr; |
542 | return *this; |
543 | } |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | |
560 | |
561 | |
562 | |
563 | |
564 | |
565 | |
566 | |
567 | |
568 | |
569 | |
570 | |
571 | |
572 | |
573 | void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { |
574 | auto &OS = *Asm->OutStreamer; |
575 | MCContext &Ctx = Asm->OutContext; |
576 | const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); |
577 | |
578 | bool VerboseAsm = OS.isVerboseAsm(); |
579 | auto AddComment = [&](const Twine &Comment) { |
580 | if (VerboseAsm) |
581 | OS.AddComment(Comment); |
582 | }; |
583 | |
584 | if (!isAArch64) { |
585 | |
586 | |
587 | StringRef FLinkageName = |
588 | GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName()); |
589 | MCSymbol *ParentFrameOffset = |
590 | Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); |
591 | const MCExpr *MCOffset = |
592 | MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx); |
593 | Asm->OutStreamer->emitAssignment(ParentFrameOffset, MCOffset); |
594 | } |
595 | |
596 | |
597 | |
598 | MCSymbol *TableBegin = |
599 | Ctx.createTempSymbol("lsda_begin", true); |
600 | MCSymbol *TableEnd = |
601 | Ctx.createTempSymbol("lsda_end", true); |
602 | const MCExpr *LabelDiff = getOffset(TableEnd, TableBegin); |
603 | const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx); |
604 | const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx); |
605 | AddComment("Number of call sites"); |
606 | OS.emitValue(EntryCount, 4); |
607 | |
608 | OS.emitLabel(TableBegin); |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | |
615 | |
616 | |
617 | const MCSymbol *LastStartLabel = nullptr; |
618 | int LastEHState = -1; |
619 | |
620 | |
621 | MachineFunction::const_iterator End = MF->end(); |
622 | MachineFunction::const_iterator Stop = std::next(MF->begin()); |
623 | while (Stop != End && !Stop->isEHFuncletEntry()) |
624 | ++Stop; |
625 | for (const auto &StateChange : |
626 | InvokeStateChangeIterator::range(FuncInfo, MF->begin(), Stop)) { |
627 | |
628 | |
629 | if (LastEHState != -1) |
630 | emitSEHActionsForRange(FuncInfo, LastStartLabel, |
631 | StateChange.PreviousEndLabel, LastEHState); |
632 | LastStartLabel = StateChange.NewStartLabel; |
633 | LastEHState = StateChange.NewState; |
634 | } |
635 | |
636 | OS.emitLabel(TableEnd); |
637 | } |
638 | |
639 | void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, |
640 | const MCSymbol *BeginLabel, |
641 | const MCSymbol *EndLabel, int State) { |
642 | auto &OS = *Asm->OutStreamer; |
643 | MCContext &Ctx = Asm->OutContext; |
644 | bool VerboseAsm = OS.isVerboseAsm(); |
645 | auto AddComment = [&](const Twine &Comment) { |
646 | if (VerboseAsm) |
647 | OS.AddComment(Comment); |
648 | }; |
649 | |
650 | assert(BeginLabel && EndLabel); |
651 | while (State != -1) { |
652 | const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State]; |
653 | const MCExpr *FilterOrFinally; |
654 | const MCExpr *ExceptOrNull; |
655 | auto *Handler = UME.Handler.get<MachineBasicBlock *>(); |
656 | if (UME.IsFinally) { |
657 | FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler)); |
658 | ExceptOrNull = MCConstantExpr::create(0, Ctx); |
659 | } else { |
660 | |
661 | |
662 | FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter) |
663 | : MCConstantExpr::create(1, Ctx); |
664 | ExceptOrNull = create32bitRef(Handler->getSymbol()); |
665 | } |
666 | |
667 | AddComment("LabelStart"); |
668 | OS.emitValue(getLabel(BeginLabel), 4); |
669 | AddComment("LabelEnd"); |
670 | OS.emitValue(getLabelPlusOne(EndLabel), 4); |
671 | AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction" |
672 | : "CatchAll"); |
673 | OS.emitValue(FilterOrFinally, 4); |
674 | AddComment(UME.IsFinally ? "Null" : "ExceptionHandler"); |
675 | OS.emitValue(ExceptOrNull, 4); |
676 | |
677 | assert(UME.ToState < State && "states should decrease"); |
678 | State = UME.ToState; |
679 | } |
680 | } |
681 | |
682 | void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { |
683 | const Function &F = MF->getFunction(); |
684 | auto &OS = *Asm->OutStreamer; |
685 | const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); |
686 | |
687 | StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName()); |
688 | |
689 | SmallVector<std::pair<const MCExpr *, int>, 4> IPToStateTable; |
690 | MCSymbol *FuncInfoXData = nullptr; |
691 | if (shouldEmitPersonality) { |
692 | |
693 | |
694 | FuncInfoXData = |
695 | Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName)); |
696 | computeIP2StateTable(MF, FuncInfo, IPToStateTable); |
697 | } else { |
698 | FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName); |
699 | } |
700 | |
701 | int UnwindHelpOffset = 0; |
702 | if (Asm->MAI->usesWindowsCFI()) |
703 | UnwindHelpOffset = |
704 | getFrameIndexOffset(FuncInfo.UnwindHelpFrameIdx, FuncInfo); |
705 | |
706 | MCSymbol *UnwindMapXData = nullptr; |
707 | MCSymbol *TryBlockMapXData = nullptr; |
708 | MCSymbol *IPToStateXData = nullptr; |
709 | if (!FuncInfo.CxxUnwindMap.empty()) |
710 | UnwindMapXData = Asm->OutContext.getOrCreateSymbol( |
711 | Twine("$stateUnwindMap$", FuncLinkageName)); |
712 | if (!FuncInfo.TryBlockMap.empty()) |
713 | TryBlockMapXData = |
714 | Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName)); |
715 | if (!IPToStateTable.empty()) |
716 | IPToStateXData = |
717 | Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName)); |
718 | |
719 | bool VerboseAsm = OS.isVerboseAsm(); |
720 | auto AddComment = [&](const Twine &Comment) { |
721 | if (VerboseAsm) |
722 | OS.AddComment(Comment); |
723 | }; |
724 | |
725 | |
726 | |
727 | |
728 | |
729 | |
730 | |
731 | |
732 | |
733 | |
734 | |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | OS.emitValueToAlignment(4); |
741 | OS.emitLabel(FuncInfoXData); |
742 | |
743 | AddComment("MagicNumber"); |
744 | OS.emitInt32(0x19930522); |
745 | |
746 | AddComment("MaxState"); |
747 | OS.emitInt32(FuncInfo.CxxUnwindMap.size()); |
748 | |
749 | AddComment("UnwindMap"); |
750 | OS.emitValue(create32bitRef(UnwindMapXData), 4); |
751 | |
752 | AddComment("NumTryBlocks"); |
753 | OS.emitInt32(FuncInfo.TryBlockMap.size()); |
754 | |
755 | AddComment("TryBlockMap"); |
756 | OS.emitValue(create32bitRef(TryBlockMapXData), 4); |
757 | |
758 | AddComment("IPMapEntries"); |
759 | OS.emitInt32(IPToStateTable.size()); |
760 | |
761 | AddComment("IPToStateXData"); |
762 | OS.emitValue(create32bitRef(IPToStateXData), 4); |
763 | |
764 | if (Asm->MAI->usesWindowsCFI()) { |
765 | AddComment("UnwindHelp"); |
766 | OS.emitInt32(UnwindHelpOffset); |
767 | } |
768 | |
769 | AddComment("ESTypeList"); |
770 | OS.emitInt32(0); |
771 | |
772 | AddComment("EHFlags"); |
773 | OS.emitInt32(1); |
774 | |
775 | |
776 | |
777 | |
778 | |
779 | if (UnwindMapXData) { |
780 | OS.emitLabel(UnwindMapXData); |
781 | for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) { |
782 | MCSymbol *CleanupSym = |
783 | getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>()); |
784 | AddComment("ToState"); |
785 | OS.emitInt32(UME.ToState); |
786 | |
787 | AddComment("Action"); |
788 | OS.emitValue(create32bitRef(CleanupSym), 4); |
789 | } |
790 | } |
791 | |
792 | |
793 | |
794 | |
795 | |
796 | |
797 | |
798 | |
799 | if (TryBlockMapXData) { |
800 | OS.emitLabel(TryBlockMapXData); |
801 | SmallVector<MCSymbol *, 1> HandlerMaps; |
802 | for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { |
803 | const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; |
804 | |
805 | MCSymbol *HandlerMapXData = nullptr; |
806 | if (!TBME.HandlerArray.empty()) |
807 | HandlerMapXData = |
808 | Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$") |
809 | .concat(Twine(I)) |
810 | .concat("$") |
811 | .concat(FuncLinkageName)); |
812 | HandlerMaps.push_back(HandlerMapXData); |
813 | |
814 | |
815 | assert(0 <= TBME.TryLow && "bad trymap interval"); |
816 | assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval"); |
817 | assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval"); |
818 | assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) && |
819 | "bad trymap interval"); |
820 | |
821 | AddComment("TryLow"); |
822 | OS.emitInt32(TBME.TryLow); |
823 | |
824 | AddComment("TryHigh"); |
825 | OS.emitInt32(TBME.TryHigh); |
826 | |
827 | AddComment("CatchHigh"); |
828 | OS.emitInt32(TBME.CatchHigh); |
829 | |
830 | AddComment("NumCatches"); |
831 | OS.emitInt32(TBME.HandlerArray.size()); |
832 | |
833 | AddComment("HandlerArray"); |
834 | OS.emitValue(create32bitRef(HandlerMapXData), 4); |
835 | } |
836 | |
837 | |
838 | unsigned ParentFrameOffset = 0; |
839 | if (shouldEmitPersonality) { |
840 | const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); |
841 | ParentFrameOffset = TFI->getWinEHParentFrameOffset(*MF); |
842 | } |
843 | |
844 | for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { |
845 | const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; |
846 | MCSymbol *HandlerMapXData = HandlerMaps[I]; |
847 | if (!HandlerMapXData) |
848 | continue; |
849 | |
850 | |
851 | |
852 | |
853 | |
854 | |
855 | |
856 | OS.emitLabel(HandlerMapXData); |
857 | for (const WinEHHandlerType &HT : TBME.HandlerArray) { |
858 | |
859 | |
860 | |
861 | const MCExpr *FrameAllocOffsetRef = nullptr; |
862 | if (HT.CatchObj.FrameIndex != INT_MAX) { |
863 | int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo); |
864 | assert(Offset != 0 && "Illegal offset for catch object!"); |
865 | FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext); |
866 | } else { |
867 | FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext); |
868 | } |
869 | |
870 | MCSymbol *HandlerSym = |
871 | getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>()); |
872 | |
873 | AddComment("Adjectives"); |
874 | OS.emitInt32(HT.Adjectives); |
875 | |
876 | AddComment("Type"); |
877 | OS.emitValue(create32bitRef(HT.TypeDescriptor), 4); |
878 | |
879 | AddComment("CatchObjOffset"); |
880 | OS.emitValue(FrameAllocOffsetRef, 4); |
881 | |
882 | AddComment("Handler"); |
883 | OS.emitValue(create32bitRef(HandlerSym), 4); |
884 | |
885 | if (shouldEmitPersonality) { |
886 | AddComment("ParentFrameOffset"); |
887 | OS.emitInt32(ParentFrameOffset); |
888 | } |
889 | } |
890 | } |
891 | } |
892 | |
893 | |
894 | |
895 | |
896 | |
897 | if (IPToStateXData) { |
898 | OS.emitLabel(IPToStateXData); |
899 | for (auto &IPStatePair : IPToStateTable) { |
900 | AddComment("IP"); |
901 | OS.emitValue(IPStatePair.first, 4); |
902 | AddComment("ToState"); |
903 | OS.emitInt32(IPStatePair.second); |
904 | } |
905 | } |
906 | } |
907 | |
908 | void WinException::computeIP2StateTable( |
909 | const MachineFunction *MF, const WinEHFuncInfo &FuncInfo, |
910 | SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) { |
911 | |
912 | for (MachineFunction::const_iterator FuncletStart = MF->begin(), |
913 | FuncletEnd = MF->begin(), |
914 | End = MF->end(); |
915 | FuncletStart != End; FuncletStart = FuncletEnd) { |
916 | |
917 | while (++FuncletEnd != End) { |
918 | if (FuncletEnd->isEHFuncletEntry()) { |
919 | break; |
920 | } |
921 | } |
922 | |
923 | |
924 | |
925 | |
926 | if (FuncletStart->isCleanupFuncletEntry()) |
927 | continue; |
928 | |
929 | MCSymbol *StartLabel; |
930 | int BaseState; |
931 | if (FuncletStart == MF->begin()) { |
932 | BaseState = NullState; |
933 | StartLabel = Asm->getFunctionBegin(); |
934 | } else { |
935 | auto *FuncletPad = |
936 | cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI()); |
937 | assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0); |
938 | BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second; |
939 | StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart); |
940 | } |
941 | assert(StartLabel && "need local function start label"); |
942 | IPToStateTable.push_back( |
943 | std::make_pair(create32bitRef(StartLabel), BaseState)); |
944 | |
945 | for (const auto &StateChange : InvokeStateChangeIterator::range( |
946 | FuncInfo, FuncletStart, FuncletEnd, BaseState)) { |
947 | |
948 | |
949 | |
950 | |
951 | const MCSymbol *ChangeLabel = StateChange.NewStartLabel; |
952 | if (!ChangeLabel) |
953 | ChangeLabel = StateChange.PreviousEndLabel; |
954 | |
955 | |
956 | |
957 | |
958 | |
959 | const MCExpr *LabelExpression = (isAArch64 || isThumb) |
960 | ? getLabel(ChangeLabel) |
961 | : getLabelPlusOne(ChangeLabel); |
962 | IPToStateTable.push_back( |
963 | std::make_pair(LabelExpression, StateChange.NewState)); |
964 | |
965 | } |
966 | } |
967 | } |
968 | |
969 | void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo, |
970 | StringRef FLinkageName) { |
971 | |
972 | |
973 | |
974 | |
975 | |
976 | |
977 | |
978 | |
979 | |
980 | int64_t Offset = 0; |
981 | int FI = FuncInfo.EHRegNodeFrameIndex; |
982 | if (FI != INT_MAX) { |
983 | const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); |
984 | Offset = TFI->getNonLocalFrameIndexReference(*Asm->MF, FI).getFixed(); |
985 | } |
986 | |
987 | MCContext &Ctx = Asm->OutContext; |
988 | MCSymbol *ParentFrameOffset = |
989 | Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); |
990 | Asm->OutStreamer->emitAssignment(ParentFrameOffset, |
991 | MCConstantExpr::create(Offset, Ctx)); |
992 | } |
993 | |
994 | |
995 | |
996 | |
997 | void WinException::emitExceptHandlerTable(const MachineFunction *MF) { |
998 | MCStreamer &OS = *Asm->OutStreamer; |
999 | const Function &F = MF->getFunction(); |
1000 | StringRef FLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName()); |
1001 | |
1002 | bool VerboseAsm = OS.isVerboseAsm(); |
1003 | auto AddComment = [&](const Twine &Comment) { |
1004 | if (VerboseAsm) |
1005 | OS.AddComment(Comment); |
1006 | }; |
1007 | |
1008 | const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); |
1009 | emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName); |
1010 | |
1011 | |
1012 | MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName); |
1013 | OS.emitValueToAlignment(4); |
1014 | OS.emitLabel(LSDALabel); |
1015 | |
1016 | const auto *Per = cast<Function>(F.getPersonalityFn()->stripPointerCasts()); |
1017 | StringRef PerName = Per->getName(); |
1018 | int BaseState = -1; |
1019 | if (PerName == "_except_handler4") { |
1020 | |
1021 | |
1022 | |
1023 | |
1024 | |
1025 | |
1026 | |
1027 | |
1028 | |
1029 | |
1030 | |
1031 | |
1032 | |
1033 | |
1034 | |
1035 | |
1036 | |
1037 | |
1038 | |
1039 | |
1040 | |
1041 | |
1042 | int GSCookieOffset = -2; |
1043 | const MachineFrameInfo &MFI = MF->getFrameInfo(); |
1044 | if (MFI.hasStackProtectorIndex()) { |
1045 | Register UnusedReg; |
1046 | const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); |
1047 | int SSPIdx = MFI.getStackProtectorIndex(); |
1048 | GSCookieOffset = |
1049 | TFI->getFrameIndexReference(*MF, SSPIdx, UnusedReg).getFixed(); |
1050 | } |
1051 | |
1052 | |
1053 | |
1054 | int EHCookieOffset = 9999; |
1055 | if (FuncInfo.EHGuardFrameIndex != INT_MAX) { |
1056 | Register UnusedReg; |
1057 | const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); |
1058 | int EHGuardIdx = FuncInfo.EHGuardFrameIndex; |
1059 | EHCookieOffset = |
1060 | TFI->getFrameIndexReference(*MF, EHGuardIdx, UnusedReg).getFixed(); |
1061 | } |
1062 | |
1063 | AddComment("GSCookieOffset"); |
1064 | OS.emitInt32(GSCookieOffset); |
1065 | AddComment("GSCookieXOROffset"); |
1066 | OS.emitInt32(0); |
1067 | AddComment("EHCookieOffset"); |
1068 | OS.emitInt32(EHCookieOffset); |
1069 | AddComment("EHCookieXOROffset"); |
1070 | OS.emitInt32(0); |
1071 | BaseState = -2; |
1072 | } |
1073 | |
1074 | assert(!FuncInfo.SEHUnwindMap.empty()); |
1075 | for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { |
1076 | auto *Handler = UME.Handler.get<MachineBasicBlock *>(); |
1077 | const MCSymbol *ExceptOrFinally = |
1078 | UME.IsFinally ? getMCSymbolForMBB(Asm, Handler) : Handler->getSymbol(); |
1079 | |
1080 | |
1081 | int ToState = UME.ToState == -1 ? BaseState : UME.ToState; |
1082 | AddComment("ToState"); |
1083 | OS.emitInt32(ToState); |
1084 | AddComment(UME.IsFinally ? "Null" : "FilterFunction"); |
1085 | OS.emitValue(create32bitRef(UME.Filter), 4); |
1086 | AddComment(UME.IsFinally ? "FinallyFunclet" : "ExceptionHandler"); |
1087 | OS.emitValue(create32bitRef(ExceptOrFinally), 4); |
1088 | } |
1089 | } |
1090 | |
1091 | static int getTryRank(const WinEHFuncInfo &FuncInfo, int State) { |
1092 | int Rank = 0; |
1093 | while (State != -1) { |
1094 | ++Rank; |
1095 | State = FuncInfo.ClrEHUnwindMap[State].TryParentState; |
1096 | } |
1097 | return Rank; |
1098 | } |
1099 | |
1100 | static int getTryAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) { |
1101 | int LeftRank = getTryRank(FuncInfo, Left); |
1102 | int RightRank = getTryRank(FuncInfo, Right); |
1103 | |
1104 | while (LeftRank < RightRank) { |
1105 | Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState; |
1106 | --RightRank; |
1107 | } |
1108 | |
1109 | while (RightRank < LeftRank) { |
1110 | Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState; |
1111 | --LeftRank; |
1112 | } |
1113 | |
1114 | while (Left != Right) { |
1115 | Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState; |
1116 | Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState; |
1117 | } |
1118 | |
1119 | return Left; |
1120 | } |
1121 | |
1122 | void WinException::emitCLRExceptionTable(const MachineFunction *MF) { |
1123 | |
1124 | |
1125 | |
1126 | MCStreamer &OS = *Asm->OutStreamer; |
1127 | const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); |
1128 | MCSymbol *FuncBeginSym = Asm->getFunctionBegin(); |
1129 | MCSymbol *FuncEndSym = Asm->getFunctionEnd(); |
1130 | |
1131 | |
1132 | struct ClrClause { |
1133 | const MCSymbol *StartLabel; |
1134 | const MCSymbol *EndLabel; |
1135 | int State; |
1136 | int EnclosingState; |
1137 | }; |
1138 | SmallVector<ClrClause, 8> Clauses; |
1139 | |
1140 | |
1141 | |
1142 | int NumStates = FuncInfo.ClrEHUnwindMap.size(); |
1143 | assert(NumStates > 0 && "Don't need exception table!"); |
1144 | DenseMap<const MachineBasicBlock *, int> HandlerStates; |
1145 | for (int State = 0; State < NumStates; ++State) { |
| 10 | | Assuming 'State' is >= 'NumStates' | |
|
| 11 | | Loop condition is false. Execution continues on line 1156 | |
|
1146 | MachineBasicBlock *HandlerBlock = |
1147 | FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>(); |
1148 | HandlerStates[HandlerBlock] = State; |
1149 | |
1150 | |
1151 | |
1152 | assert(FuncInfo.ClrEHUnwindMap[State].HandlerParentState < State && |
1153 | "ill-formed state numbering"); |
1154 | } |
1155 | |
1156 | HandlerStates[&MF->front()] = NullState; |
1157 | |
1158 | |
1159 | |
1160 | OS.emitInt32(0xffffffff); |
1161 | |
1162 | OS.emitInt32(NumStates); |
1163 | |
1164 | |
1165 | |
1166 | |
1167 | |
1168 | |
1169 | |
1170 | |
1171 | |
1172 | |
1173 | |
1174 | |
1175 | |
1176 | |
1177 | |
1178 | |
1179 | SmallVector<std::pair<const MCSymbol *, int>, 4> HandlerStack; |
1180 | |
1181 | std::unique_ptr<MCSymbol *[]> EndSymbolMap(new MCSymbol *[NumStates]); |
| |
1182 | SmallVector<int, 4> MinClauseMap((size_t)NumStates, NumStates); |
1183 | |
1184 | |
1185 | for (MachineFunction::const_iterator FuncletStart = MF->begin(), |
| 13 | | Loop condition is true. Entering loop body | |
|
1186 | FuncletEnd = MF->begin(), |
1187 | End = MF->end(); |
1188 | FuncletStart != End; FuncletStart = FuncletEnd) { |
1189 | int FuncletState = HandlerStates[&*FuncletStart]; |
1190 | |
1191 | MCSymbol *EndSymbol = FuncEndSym; |
1192 | while (++FuncletEnd != End) { |
| 14 | | Loop condition is false. Execution continues on line 1200 | |
|
1193 | if (FuncletEnd->isEHFuncletEntry()) { |
1194 | EndSymbol = getMCSymbolForMBB(Asm, &*FuncletEnd); |
1195 | break; |
1196 | } |
1197 | } |
1198 | |
1199 | |
1200 | OS.emitValue(getOffset(EndSymbol, FuncBeginSym), 4); |
1201 | if (FuncletState != NullState) { |
| 15 | | Assuming 'FuncletState' is not equal to 'NullState' | |
|
| |
1202 | |
1203 | EndSymbolMap[FuncletState] = EndSymbol; |
| 17 | | Use of zero-allocated memory |
|
1204 | } |
1205 | |
1206 | |
1207 | |
1208 | const MCSymbol *CurrentStartLabel = nullptr; |
1209 | int CurrentState = NullState; |
1210 | assert(HandlerStack.empty()); |
1211 | for (const auto &StateChange : |
1212 | InvokeStateChangeIterator::range(FuncInfo, FuncletStart, FuncletEnd)) { |
1213 | |
1214 | int StillPendingState = |
1215 | getTryAncestor(FuncInfo, CurrentState, StateChange.NewState); |
1216 | while (CurrentState != StillPendingState) { |
1217 | assert(CurrentState != NullState && |
1218 | "Failed to find still-pending state!"); |
1219 | |
1220 | Clauses.push_back({CurrentStartLabel, StateChange.PreviousEndLabel, |
1221 | CurrentState, FuncletState}); |
1222 | |
1223 | CurrentState = FuncInfo.ClrEHUnwindMap[CurrentState].TryParentState; |
1224 | |
1225 | |
1226 | if (HandlerStack.back().second == CurrentState) |
1227 | CurrentStartLabel = HandlerStack.pop_back_val().first; |
1228 | } |
1229 | |
1230 | if (StateChange.NewState != CurrentState) { |
1231 | |
1232 | |
1233 | |
1234 | for (int EnteredState = StateChange.NewState; |
1235 | EnteredState != CurrentState; |
1236 | EnteredState = |
1237 | FuncInfo.ClrEHUnwindMap[EnteredState].TryParentState) { |
1238 | int &MinEnclosingState = MinClauseMap[EnteredState]; |
1239 | if (FuncletState < MinEnclosingState) |
1240 | MinEnclosingState = FuncletState; |
1241 | } |
1242 | |
1243 | |
1244 | HandlerStack.emplace_back(CurrentStartLabel, CurrentState); |
1245 | CurrentStartLabel = StateChange.NewStartLabel; |
1246 | CurrentState = StateChange.NewState; |
1247 | } |
1248 | } |
1249 | assert(HandlerStack.empty()); |
1250 | } |
1251 | |
1252 | |
1253 | OS.emitInt32(Clauses.size()); |
1254 | for (ClrClause &Clause : Clauses) { |
1255 | |
1256 | |
1257 | |
1258 | |
1259 | |
1260 | |
1261 | |
1262 | |
1263 | |
1264 | |
1265 | |
1266 | |
1267 | |
1268 | |
1269 | |
1270 | |
1271 | |
1272 | |
1273 | |
1274 | |
1275 | |
1276 | |
1277 | |
1278 | |
1279 | |
1280 | |
1281 | |
1282 | |
1283 | |
1284 | |
1285 | |
1286 | |
1287 | |
1288 | |
1289 | |
1290 | |
1291 | |
1292 | |
1293 | |
1294 | |
1295 | |
1296 | |
1297 | |
1298 | |
1299 | |
1300 | |
1301 | |
1302 | |
1303 | const MCExpr *ClauseBegin = |
1304 | getOffsetPlusOne(Clause.StartLabel, FuncBeginSym); |
1305 | const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym); |
1306 | |
1307 | const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State]; |
1308 | MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>(); |
1309 | MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock); |
1310 | const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym); |
1311 | MCSymbol *EndSym = EndSymbolMap[Clause.State]; |
1312 | const MCExpr *HandlerEnd = getOffset(EndSym, FuncBeginSym); |
1313 | |
1314 | uint32_t Flags = 0; |
1315 | switch (Entry.HandlerType) { |
1316 | case ClrHandlerType::Catch: |
1317 | |
1318 | break; |
1319 | case ClrHandlerType::Filter: |
1320 | Flags |= 1; |
1321 | break; |
1322 | case ClrHandlerType::Finally: |
1323 | Flags |= 2; |
1324 | break; |
1325 | case ClrHandlerType::Fault: |
1326 | Flags |= 4; |
1327 | break; |
1328 | } |
1329 | if (Clause.EnclosingState != MinClauseMap[Clause.State]) { |
1330 | |
1331 | |
1332 | assert(Clause.EnclosingState > MinClauseMap[Clause.State]); |
1333 | Flags |= 8; |
1334 | } |
1335 | OS.emitInt32(Flags); |
1336 | |
1337 | |
1338 | OS.emitValue(ClauseBegin, 4); |
1339 | OS.emitValue(ClauseEnd, 4); |
1340 | |
1341 | |
1342 | OS.emitValue(HandlerBegin, 4); |
1343 | OS.emitValue(HandlerEnd, 4); |
1344 | |
1345 | |
1346 | assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters"); |
1347 | OS.emitInt32(Entry.TypeToken); |
1348 | } |
1349 | } |