llvm.org GIT mirror llvm / c181443
[WinEH] Fix ip2state table emission with funclets Previously we were hijacking the old LandingPadInfo data structures to communicate our state numbers. Now we don't need that anymore. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248763 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
8 changed file(s) with 184 addition(s) and 99 deletion(s). Raw diff Collapse all Expand all
2727 class InvokeInst;
2828 class IntrinsicInst;
2929 class LandingPadInst;
30 class MCExpr;
3031 class MCSymbol;
3132 class MachineBasicBlock;
3233 class Value;
159160
160161 struct WinEHFuncInfo {
161162 DenseMap EHPadStateMap;
163 DenseMap> InvokeToStateMap;
162164 SmallVector UnwindMap;
163165 SmallVector TryBlockMap;
164166 SmallVector SEHUnwindMap;
165 SmallVector, 4> IPToStateList;
166167 int UnwindHelpFrameIdx = INT_MAX;
167168 int UnwindHelpFrameOffset = -1;
168169
169170 int getLastStateNumber() const { return UnwindMap.size() - 1; }
171
172 void addIPToStateRange(const BasicBlock *PadBB, MCSymbol *InvokeBegin,
173 MCSymbol *InvokeEnd);
170174
171175 /// localescape index of the 32-bit EH registration node. Set by
172176 /// WinEHStatePass and used indirectly by SEH filter functions of the parent.
964964 EmitFunctionBodyEnd();
965965
966966 if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
967 MAI->hasDotTypeDotSizeDirective()) {
967 MMI->hasEHFunclets() || MAI->hasDotTypeDotSizeDirective()) {
968968 // Create a symbol for the end of function.
969969 CurrentFnEnd = createTempSymbol("func_end");
970970 OutStreamer->EmitLabel(CurrentFnEnd);
12591259 CurExceptionSym = nullptr;
12601260 bool NeedsLocalForSize = MAI->needsLocalForSize();
12611261 if (!MMI->getLandingPads().empty() || MMI->hasDebugInfo() ||
1262 NeedsLocalForSize) {
1262 MMI->hasEHFunclets() || NeedsLocalForSize) {
12631263 CurrentFnBegin = createTempSymbol("func_begin");
12641264 if (NeedsLocalForSize)
12651265 CurrentFnSymForSize = CurrentFnBegin;
173173 if (const auto *GV = dyn_cast(V))
174174 return create32bitRef(Asm->getSymbol(GV));
175175 return create32bitRef(MMI->getAddrLabelSymbol(cast(V)));
176 }
177
178 const MCExpr *WinException::getLabelPlusOne(MCSymbol *Label) {
179 return MCBinaryExpr::createAdd(create32bitRef(Label),
180 MCConstantExpr::create(1, Asm->OutContext),
181 Asm->OutContext);
176182 }
177183
178184 /// Emit the language-specific data that __C_specific_handler expects. This
262268 if (CSE.EndLabel) {
263269 // The interval is half-open, so we have to add one to include the return
264270 // address of the last invoke in the range.
265 End = MCBinaryExpr::createAdd(create32bitRef(CSE.EndLabel),
266 MCConstantExpr::create(1, Asm->OutContext),
267 Asm->OutContext);
271 End = getLabelPlusOne(CSE.EndLabel);
268272 } else {
269273 End = create32bitRef(EHFuncEndSym);
270274 }
311315
312316 StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName());
313317
318 SmallVector, 4> IPToStateTable;
314319 MCSymbol *FuncInfoXData = nullptr;
315320 if (shouldEmitPersonality) {
321 // If we're 64-bit, emit a pointer to the C++ EH data, and build a map from
322 // IPs to state numbers.
316323 FuncInfoXData =
317324 Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName));
318325 OS.EmitValue(create32bitRef(FuncInfoXData), 4);
319
320 extendIP2StateTable(MF, FuncInfo);
326 computeIP2StateTable(MF, FuncInfo, IPToStateTable);
321327 } else {
322328 FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName);
323329 emitEHRegistrationOffsetLabel(FuncInfo, FuncLinkageName);
332338 if (!FuncInfo.TryBlockMap.empty())
333339 TryBlockMapXData =
334340 Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName));
335 if (!FuncInfo.IPToStateList.empty())
341 if (!IPToStateTable.empty())
336342 IPToStateXData =
337343 Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName));
338344
358364 OS.EmitValue(create32bitRef(UnwindMapXData), 4); // UnwindMap
359365 OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks
360366 OS.EmitValue(create32bitRef(TryBlockMapXData), 4); // TryBlockMap
361 OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4); // IPMapEntries
367 OS.EmitIntValue(IPToStateTable.size(), 4); // IPMapEntries
362368 OS.EmitValue(create32bitRef(IPToStateXData), 4); // IPToStateMap
363369 if (Asm->MAI->usesWindowsCFI())
364370 OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
476482 // };
477483 if (IPToStateXData) {
478484 OS.EmitLabel(IPToStateXData);
479 for (auto &IPStatePair : FuncInfo.IPToStateList) {
480 OS.EmitValue(create32bitRef(IPStatePair.first), 4); // IP
481 OS.EmitIntValue(IPStatePair.second, 4); // State
482 }
483 }
484 }
485
486 void WinException::extendIP2StateTable(const MachineFunction *MF,
487 WinEHFuncInfo &FuncInfo) {
488 // The Itanium LSDA table sorts similar landing pads together to simplify the
489 // actions table, but we don't need that.
490 SmallVector LandingPads;
491 const std::vector &PadInfos = MMI->getLandingPads();
492 LandingPads.reserve(PadInfos.size());
493 for (const auto &LP : PadInfos)
494 LandingPads.push_back(&LP);
495
496 RangeMapType PadMap;
497 computePadMap(LandingPads, PadMap);
498
499 // The end label of the previous invoke or nounwind try-range.
500 MCSymbol *LastLabel = Asm->getFunctionBegin();
501
485 for (auto &IPStatePair : IPToStateTable) {
486 OS.EmitValue(IPStatePair.first, 4); // IP
487 OS.EmitIntValue(IPStatePair.second, 4); // State
488 }
489 }
490 }
491
492 void WinException::computeIP2StateTable(
493 const MachineFunction *MF, WinEHFuncInfo &FuncInfo,
494 SmallVectorImpl> &IPToStateTable) {
502495 // Whether there is a potentially throwing instruction (currently this means
503496 // an ordinary call) between the end of the previous try-range and now.
504 bool SawPotentiallyThrowing = false;
505
506 int LastEHState = -2;
507
508 // The parent function and the catch handlers contribute to the 'ip2state'
509 // table.
510
511 // Include ip2state entries for the beginning of the main function and
512 // for catch handler functions.
513 FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
514 LastEHState = -1;
497 bool SawPotentiallyThrowing = true;
498
499 // Remember what state we were in the last time we found a begin try label.
500 // This allows us to coalesce many nearby invokes with the same state into one
501 // entry.
502 int LastEHState = -1;
503 MCSymbol *LastEndLabel = Asm->getFunctionBegin();
504 assert(LastEndLabel && "need local function start label");
505
506 // Indicate that all calls from the prologue to the first invoke unwind to
507 // caller. We handle this as a special case since other ranges starting at end
508 // labels need to use LtmpN+1.
509 IPToStateTable.push_back(std::make_pair(create32bitRef(LastEndLabel), -1));
510
515511 for (const auto &MBB : *MF) {
512 // FIXME: Do we need to emit entries for funclet base states?
513
516514 for (const auto &MI : MBB) {
515 // Find all the EH_LABEL instructions, tracking if we've crossed a
516 // potentially throwing call since the last label.
517517 if (!MI.isEHLabel()) {
518518 if (MI.isCall())
519519 SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
520520 continue;
521521 }
522522
523 // End of the previous try-range?
524 MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
525 if (BeginLabel == LastLabel)
523 // If this was an end label, return SawPotentiallyThrowing to the start
524 // state and keep going. Otherwise, we will consider the call between the
525 // begin/end labels to be a potentially throwing call and generate extra
526 // table entries.
527 MCSymbol *Label = MI.getOperand(0).getMCSymbol();
528 if (Label == LastEndLabel)
526529 SawPotentiallyThrowing = false;
527530
528 // Beginning of a new try-range?
529 RangeMapType::const_iterator L = PadMap.find(BeginLabel);
530 if (L == PadMap.end())
531 // Nope, it was just some random label.
531 // Check if this was a begin label. Otherwise, it must be an end label or
532 // some random label, and we should continue.
533 auto StateAndEnd = FuncInfo.InvokeToStateMap.find(Label);
534 if (StateAndEnd == FuncInfo.InvokeToStateMap.end())
532535 continue;
533536
534 const PadRange &P = L->second;
535 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
536 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
537 "Inconsistent landing pad map!");
538
539 // FIXME: Should this be using FuncInfo.HandlerBaseState?
537 // Extract the state and end label.
538 int State;
539 MCSymbol *EndLabel;
540 std::tie(State, EndLabel) = StateAndEnd->second;
541
542 // If there was a potentially throwing call between this begin label and
543 // the last end label, we need an extra base state entry to indicate that
544 // those calls unwind directly to the caller.
540545 if (SawPotentiallyThrowing && LastEHState != -1) {
541 FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
546 IPToStateTable.push_back(
547 std::make_pair(getLabelPlusOne(LastEndLabel), -1));
542548 SawPotentiallyThrowing = false;
543549 LastEHState = -1;
544550 }
545551
546 if (LandingPad->WinEHState != LastEHState)
547 FuncInfo.IPToStateList.push_back(
548 std::make_pair(BeginLabel, LandingPad->WinEHState));
549 LastEHState = LandingPad->WinEHState;
550 LastLabel = LandingPad->EndLabels[P.RangeIndex];
551 }
552 // Emit an entry indicating that PCs after 'Label' have this EH state.
553 if (State != LastEHState)
554 IPToStateTable.push_back(std::make_pair(create32bitRef(Label), State));
555 LastEHState = State;
556 LastEndLabel = EndLabel;
557 }
558 }
559
560 if (LastEndLabel != Asm->getFunctionBegin()) {
561 // Indicate that all calls from the last invoke until the epilogue unwind to
562 // caller. This also ensures that we have at least one ip2state entry, if
563 // somehow all invokes were deleted during CodeGen.
564 IPToStateTable.push_back(std::make_pair(getLabelPlusOne(LastEndLabel), -1));
552565 }
553566 }
554567
4646 /// tables.
4747 void emitExceptHandlerTable(const MachineFunction *MF);
4848
49 void extendIP2StateTable(const MachineFunction *MF, WinEHFuncInfo &FuncInfo);
49 void computeIP2StateTable(
50 const MachineFunction *MF, WinEHFuncInfo &FuncInfo,
51 SmallVectorImpl> &IPToStateTable);
5052
5153 /// Emits the label used with llvm.x86.seh.recoverfp, which is used by
5254 /// outlined funclets.
5557
5658 const MCExpr *create32bitRef(const MCSymbol *Value);
5759 const MCExpr *create32bitRef(const Value *V);
60 const MCExpr *getLabelPlusOne(MCSymbol *Label);
5861
5962 public:
6063 //===--------------------------------------------------------------------===//
52615261 DAG.setRoot(DAG.getEHLabel(getCurSDLoc(), getRoot(), EndLabel));
52625262
52635263 // Inform MachineModuleInfo of range.
5264 MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel);
5264 if (MMI.hasEHFunclets()) {
5265 WinEHFuncInfo &EHInfo =
5266 MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction());
5267 EHInfo.addIPToStateRange(EHPadBB, BeginLabel, EndLabel);
5268 } else {
5269 MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel);
5270 }
52655271 }
52665272
52675273 return Result;
3333 #include "llvm/IR/IntrinsicInst.h"
3434 #include "llvm/IR/Module.h"
3535 #include "llvm/IR/PatternMatch.h"
36 #include "llvm/MC/MCSymbol.h"
3637 #include "llvm/Pass.h"
3738 #include "llvm/Support/Debug.h"
3839 #include "llvm/Support/raw_ostream.h"
34983499 U.set(Load);
34993500 }
35003501 }
3502
3503 void WinEHFuncInfo::addIPToStateRange(const BasicBlock *PadBB,
3504 MCSymbol *InvokeBegin,
3505 MCSymbol *InvokeEnd) {
3506 assert(PadBB->isEHPad() && EHPadStateMap.count(PadBB->getFirstNonPHI()) &&
3507 "should get EH pad BB with precomputed state");
3508 InvokeToStateMap[InvokeBegin] =
3509 std::make_pair(EHPadStateMap[PadBB->getFirstNonPHI()], InvokeEnd);
3510 }
118118 ; X86-NEXT: .long [[catch2bb]]
119119
120120 ; X64-LABEL: try_catch_catch:
121 ; X64: Lfunc_begin0:
121122 ; X64: pushq %rbp
122123 ; X64: .seh_pushreg 5
123124 ; X64: subq $48, %rsp
124125 ; X64: .seh_stackalloc 48
125126 ; X64: leaq 48(%rsp), %rbp
126127 ; X64: .seh_setframe 5, 48
128 ; X64: .Ltmp0
127129 ; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx
128130 ; X64-DAG: movl $1, %ecx
129131 ; X64: callq f
137139 ; X64: pushq %rbp
138140 ; X64: movq %rdx, %rbp
139141 ; X64: subq $32, %rsp
142 ; X64-DAG: .Ltmp4
140143 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
141144 ; X64-DAG: movl [[e_addr:[-0-9]+]](%rbp), %ecx
142145 ; X64: callq f
153156 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
154157 ; X64-DAG: movl $3, %ecx
155158 ; X64: callq f
159 ; X64: .Ltmp3
156160 ; X64: addq $32, %rsp
157161 ; X64-NEXT: popq %rbp
158162 ; X64-NEXT: leaq [[contbb]](%rip), %rax
159163 ; X64-NEXT: retq
160164
165 ; X64: $cppxdata$try_catch_catch:
166 ; X64-NEXT: .long 429065506
167 ; X64-NEXT: .long 2
168 ; X64-NEXT: .long ($stateUnwindMap$try_catch_catch)@IMGREL
169 ; X64-NEXT: .long 1
170 ; X64-NEXT: .long ($tryMap$try_catch_catch)@IMGREL
171 ; X64-NEXT: .long 4
172 ; X64-NEXT: .long ($ip2state$try_catch_catch)@IMGREL
173 ; X64-NEXT: .long 32
174 ; X64-NEXT: .long 0
175 ; X64-NEXT: .long 1
176
177 ; X64: $tryMap$try_catch_catch:
178 ; X64-NEXT: .long 0
179 ; X64-NEXT: .long 0
180 ; X64-NEXT: .long 1
181 ; X64-NEXT: .long 2
182 ; X64-NEXT: .long ($handlerMap$0$try_catch_catch)@IMGREL
183
161184 ; X64: $handlerMap$0$try_catch_catch:
162 ; X64: .long 0
163 ; X64: .long "??_R0H@8"@IMGREL
185 ; X64-NEXT: .long 0
186 ; X64-NEXT: .long "??_R0H@8"@IMGREL
164187 ; FIXME: This should probably be offset from rsp, not rbp.
165 ; X64: .long [[e_addr]]
166 ; X64: .long [[catch1bb]]@IMGREL
167 ; X64: .long 56
168 ; X64: .long 64
169 ; X64: .long 0
170 ; X64: .long 0
171 ; X64: .long [[catch2bb]]@IMGREL
172 ; X64: .long 56
188 ; X64-NEXT: .long [[e_addr]]
189 ; X64-NEXT: .long [[catch1bb]]@IMGREL
190 ; X64-NEXT: .long 56
191 ; X64-NEXT: .long 64
192 ; X64-NEXT: .long 0
193 ; X64-NEXT: .long 0
194 ; X64-NEXT: .long [[catch2bb]]@IMGREL
195 ; X64-NEXT: .long 56
196
197 ; X64: $ip2state$try_catch_catch:
198 ; X64-NEXT: .long .Lfunc_begin0@IMGREL
199 ; X64-NEXT: .long -1
200 ; X64-NEXT: .long .Ltmp0@IMGREL
201 ; X64-NEXT: .long 0
202 ; X64-NEXT: .long .Ltmp4@IMGREL
203 ; X64-NEXT: .long 1
204 ; X64-NEXT: .long .Ltmp3@IMGREL+1
205 ; X64-NEXT: .long -1
9595 ; X86: .long LBB1_[[cleanup_inner]]
9696
9797 ; X64-LABEL: nested_cleanup:
98 ; X64: .Lfunc_begin1:
99 ; X64: .Ltmp8:
98100 ; X64: movl $1, %ecx
99101 ; X64: callq f
102 ; X64: .Ltmp10:
100103 ; X64: movl $2, %ecx
101104 ; X64: callq f
105 ; X64: .Ltmp11:
106 ; X64: callq "??1Dtor@@QAE@XZ"
107 ; X64: .Ltmp12:
102108 ; X64: movl $3, %ecx
103109 ; X64: callq f
110 ; X64: .Ltmp13:
104111
105112 ; X64: .LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner
106113 ; X64: pushq %rbp
116123 ; X64: popq %rbp
117124 ; X64: retq
118125
119 ; X64: .seh_handlerdata
120 ; X64: .long ($cppxdata$nested_cleanup)@IMGREL
121 ; X64: .align 4
122 ; X64:$cppxdata$nested_cleanup:
123 ; X64: .long 429065506
124 ; X64: .long 2
125 ; X64: .long ($stateUnwindMap$nested_cleanup)@IMGREL
126 ; X64: .long 0
127 ; X64: .long 0
128 ; X64: .long 1
129 ; X64: .long ($ip2state$nested_cleanup)@IMGREL
130 ; X64: .long 40
131 ; X64: .long 0
132 ; X64: .long 1
133 ; X64:$stateUnwindMap$nested_cleanup:
134 ; X64: .long -1
135 ; X64: .long .LBB1_[[cleanup_outer]]@IMGREL
136 ; X64: .long 0
137 ; X64: .long .LBB1_[[cleanup_inner]]@IMGREL
138 ; FIXME: The ip2state table is totally wrong.
139 ; X64:$ip2state$nested_cleanup:
140 ; X64: .long .Lfunc_begin1@IMGREL
141 ; X64: .long -1
126 ; X64: .seh_handlerdata
127 ; X64-NEXT: .long ($cppxdata$nested_cleanup)@IMGREL
128 ; X64-NEXT: .align 4
129 ; X64: $cppxdata$nested_cleanup:
130 ; X64-NEXT: .long 429065506
131 ; X64-NEXT: .long 2
132 ; X64-NEXT: .long ($stateUnwindMap$nested_cleanup)@IMGREL
133 ; X64-NEXT: .long 0
134 ; X64-NEXT: .long 0
135 ; X64-NEXT: .long 5
136 ; X64-NEXT: .long ($ip2state$nested_cleanup)@IMGREL
137 ; X64-NEXT: .long 40
138 ; X64-NEXT: .long 0
139 ; X64-NEXT: .long 1
140
141 ; X64: $stateUnwindMap$nested_cleanup:
142 ; X64-NEXT: .long -1
143 ; X64-NEXT: .long .LBB1_[[cleanup_outer]]@IMGREL
144 ; X64-NEXT: .long 0
145 ; X64-NEXT: .long .LBB1_[[cleanup_inner]]@IMGREL
146
147 ; X64: $ip2state$nested_cleanup:
148 ; X64-NEXT: .long .Lfunc_begin1@IMGREL
149 ; X64-NEXT: .long -1
150 ; X64-NEXT: .long .Ltmp8@IMGREL
151 ; X64-NEXT: .long 0
152 ; X64-NEXT: .long .Ltmp10@IMGREL
153 ; X64-NEXT: .long 1
154 ; X64-NEXT: .long .Ltmp12@IMGREL
155 ; X64-NEXT: .long 0
156 ; X64-NEXT: .long .Ltmp13@IMGREL+1
157 ; X64-NEXT: .long -1
142158
143159 attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
144160 attributes #1 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }