Skip to content

Commit e476bec

Browse files
committed
Mark the beginning and end of epilogs for Win x64
1 parent 26029d7 commit e476bec

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+399
-66
lines changed

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ class MCStreamer {
252252
bool AllowAutoPadding = false;
253253

254254
protected:
255+
// True if we are processing SEH directives in an epilogue.
256+
bool InEpilogCFI = false;
257+
258+
// Symbol of the current epilog for which we are processing SEH directives.
259+
MCSymbol *CurrentEpilog = nullptr;
260+
255261
MCFragment *CurFrag = nullptr;
256262

257263
MCStreamer(MCContext &Ctx);
@@ -331,6 +337,10 @@ class MCStreamer {
331337
return WinFrameInfos;
332338
}
333339

340+
MCSymbol *getCurrentEpilog() const { return CurrentEpilog; }
341+
342+
bool isInEpilogCFI() const { return InEpilogCFI; }
343+
334344
void generateCompactUnwindEncodings(MCAsmBackend *MAB);
335345

336346
/// \name Assembly File Formatting.
@@ -1043,6 +1053,8 @@ class MCStreamer {
10431053
SMLoc Loc = SMLoc());
10441054
virtual void emitWinCFIPushFrame(bool Code, SMLoc Loc = SMLoc());
10451055
virtual void emitWinCFIEndProlog(SMLoc Loc = SMLoc());
1056+
virtual void emitWinCFIBeginEpilogue(SMLoc Loc = SMLoc());
1057+
virtual void emitWinCFIEndEpilogue(SMLoc Loc = SMLoc());
10461058
virtual void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
10471059
SMLoc Loc = SMLoc());
10481060
virtual void emitWinEHHandlerData(SMLoc Loc = SMLoc());

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ class MCAsmStreamer final : public MCStreamer {
391391
SMLoc Loc) override;
392392
void emitWinCFIPushFrame(bool Code, SMLoc Loc) override;
393393
void emitWinCFIEndProlog(SMLoc Loc) override;
394+
void emitWinCFIBeginEpilogue(SMLoc Loc) override;
395+
void emitWinCFIEndEpilogue(SMLoc Loc) override;
394396

395397
void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
396398
SMLoc Loc) override;
@@ -2306,6 +2308,20 @@ void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) {
23062308
EmitEOL();
23072309
}
23082310

2311+
void MCAsmStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) {
2312+
MCStreamer::emitWinCFIBeginEpilogue(Loc);
2313+
2314+
OS << "\t.seh_beginepilogue";
2315+
EmitEOL();
2316+
}
2317+
2318+
void MCAsmStreamer::emitWinCFIEndEpilogue(SMLoc Loc) {
2319+
MCStreamer::emitWinCFIEndEpilogue(Loc);
2320+
2321+
OS << "\t.seh_endepilogue";
2322+
EmitEOL();
2323+
}
2324+
23092325
void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
23102326
const MCSymbolRefExpr *To,
23112327
uint64_t Count) {

llvm/lib/MC/MCParser/COFFAsmParser.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ class COFFAsmParser : public MCAsmParserExtension {
9090
".seh_stackalloc");
9191
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndProlog>(
9292
".seh_endprologue");
93+
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveBeginEpilog>(
94+
".seh_beginepilogue");
95+
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveEndEpilog>(
96+
".seh_endepilogue");
9397
}
9498

9599
bool ParseSectionDirectiveText(StringRef, SMLoc) {
@@ -137,6 +141,8 @@ class COFFAsmParser : public MCAsmParserExtension {
137141
bool ParseSEHDirectiveHandlerData(StringRef, SMLoc);
138142
bool ParseSEHDirectiveAllocStack(StringRef, SMLoc);
139143
bool ParseSEHDirectiveEndProlog(StringRef, SMLoc);
144+
bool ParseSEHDirectiveBeginEpilog(StringRef, SMLoc);
145+
bool ParseSEHDirectiveEndEpilog(StringRef, SMLoc);
140146

141147
bool ParseAtUnwindOrAtExcept(bool &unwind, bool &except);
142148
bool ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc);
@@ -715,6 +721,18 @@ bool COFFAsmParser::ParseSEHDirectiveEndProlog(StringRef, SMLoc Loc) {
715721
return false;
716722
}
717723

724+
bool COFFAsmParser::ParseSEHDirectiveBeginEpilog(StringRef, SMLoc Loc) {
725+
Lex();
726+
getStreamer().emitWinCFIBeginEpilogue(Loc);
727+
return false;
728+
}
729+
730+
bool COFFAsmParser::ParseSEHDirectiveEndEpilog(StringRef, SMLoc Loc) {
731+
Lex();
732+
getStreamer().emitWinCFIEndEpilogue(Loc);
733+
return false;
734+
}
735+
718736
bool COFFAsmParser::ParseAtUnwindOrAtExcept(bool &unwind, bool &except) {
719737
StringRef identifier;
720738
if (getLexer().isNot(AsmToken::At) && getLexer().isNot(AsmToken::Percent))

llvm/lib/MC/MCStreamer.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,26 @@ void MCStreamer::emitWinCFIEndProlog(SMLoc Loc) {
979979
CurFrame->PrologEnd = Label;
980980
}
981981

982+
void MCStreamer::emitWinCFIBeginEpilogue(SMLoc Loc) {
983+
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
984+
if (!CurFrame)
985+
return;
986+
987+
InEpilogCFI = true;
988+
CurrentEpilog = emitCFILabel();
989+
}
990+
991+
void MCStreamer::emitWinCFIEndEpilogue(SMLoc Loc) {
992+
WinEH::FrameInfo *CurFrame = EnsureValidWinFrameInfo(Loc);
993+
if (!CurFrame)
994+
return;
995+
996+
InEpilogCFI = false;
997+
MCSymbol *Label = emitCFILabel();
998+
CurFrame->EpilogMap[CurrentEpilog].End = Label;
999+
CurrentEpilog = nullptr;
1000+
}
1001+
9821002
void MCStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {}
9831003

9841004
void MCStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {}

llvm/lib/Target/AArch64/MCTargetDesc/AArch64TargetStreamer.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,6 @@ class AArch64TargetELFStreamer : public AArch64TargetStreamer {
100100
};
101101

102102
class AArch64TargetWinCOFFStreamer : public llvm::AArch64TargetStreamer {
103-
private:
104-
// True if we are processing SEH directives in an epilogue.
105-
bool InEpilogCFI = false;
106-
107-
// Symbol of the current epilog for which we are processing SEH directives.
108-
MCSymbol *CurrentEpilog = nullptr;
109103
public:
110104
AArch64TargetWinCOFFStreamer(llvm::MCStreamer &S)
111105
: AArch64TargetStreamer(S) {}

llvm/lib/Target/AArch64/MCTargetDesc/AArch64WinCOFFStreamer.cpp

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinUnwindCode(unsigned UnwindCode,
7373
if (!CurFrame)
7474
return;
7575
auto Inst = WinEH::Instruction(UnwindCode, /*Label=*/nullptr, Reg, Offset);
76-
if (InEpilogCFI)
77-
CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
76+
if (S.isInEpilogCFI())
77+
CurFrame->EpilogMap[S.getCurrentEpilog()].Instructions.push_back(Inst);
7878
else
7979
CurFrame->Instructions.push_back(Inst);
8080
}
@@ -183,13 +183,7 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFIPrologEnd() {
183183
}
184184

185185
void AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogStart() {
186-
auto &S = getStreamer();
187-
WinEH::FrameInfo *CurFrame = S.EnsureValidWinFrameInfo(SMLoc());
188-
if (!CurFrame)
189-
return;
190-
191-
InEpilogCFI = true;
192-
CurrentEpilog = S.emitCFILabel();
186+
getStreamer().emitWinCFIBeginEpilogue();
193187
}
194188

195189
void AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogEnd() {
@@ -198,13 +192,10 @@ void AArch64TargetWinCOFFStreamer::emitARM64WinCFIEpilogEnd() {
198192
if (!CurFrame)
199193
return;
200194

201-
InEpilogCFI = false;
202195
WinEH::Instruction Inst =
203196
WinEH::Instruction(Win64EH::UOP_End, /*Label=*/nullptr, -1, 0);
204-
CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
205-
MCSymbol *Label = S.emitCFILabel();
206-
CurFrame->EpilogMap[CurrentEpilog].End = Label;
207-
CurrentEpilog = nullptr;
197+
CurFrame->EpilogMap[S.getCurrentEpilog()].Instructions.push_back(Inst);
198+
S.emitWinCFIEndEpilogue();
208199
}
209200

210201
void AArch64TargetWinCOFFStreamer::emitARM64WinCFITrapFrame() {

llvm/lib/Target/ARM/MCTargetDesc/ARMWinCOFFStreamer.cpp

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,6 @@ llvm::createARMWinCOFFStreamer(MCContext &Context,
7777

7878
namespace {
7979
class ARMTargetWinCOFFStreamer : public llvm::ARMTargetStreamer {
80-
private:
81-
// True if we are processing SEH directives in an epilogue.
82-
bool InEpilogCFI = false;
83-
84-
// Symbol of the current epilog for which we are processing SEH directives.
85-
MCSymbol *CurrentEpilog = nullptr;
86-
8780
public:
8881
ARMTargetWinCOFFStreamer(llvm::MCStreamer &S) : ARMTargetStreamer(S) {}
8982

@@ -114,8 +107,8 @@ void ARMTargetWinCOFFStreamer::emitARMWinUnwindCode(unsigned UnwindCode,
114107
return;
115108
MCSymbol *Label = S.emitCFILabel();
116109
auto Inst = WinEH::Instruction(UnwindCode, Label, Reg, Offset);
117-
if (InEpilogCFI)
118-
CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
110+
if (S.isInEpilogCFI())
111+
CurFrame->EpilogMap[S.getCurrentEpilog()].Instructions.push_back(Inst);
119112
else
120113
CurFrame->Instructions.push_back(Inst);
121114
}
@@ -224,9 +217,8 @@ void ARMTargetWinCOFFStreamer::emitARMWinCFIEpilogStart(unsigned Condition) {
224217
if (!CurFrame)
225218
return;
226219

227-
InEpilogCFI = true;
228-
CurrentEpilog = S.emitCFILabel();
229-
CurFrame->EpilogMap[CurrentEpilog].Condition = Condition;
220+
S.emitWinCFIBeginEpilogue();
221+
CurFrame->EpilogMap[S.getCurrentEpilog()].Condition = Condition;
230222
}
231223

232224
void ARMTargetWinCOFFStreamer::emitARMWinCFIEpilogEnd() {
@@ -235,14 +227,14 @@ void ARMTargetWinCOFFStreamer::emitARMWinCFIEpilogEnd() {
235227
if (!CurFrame)
236228
return;
237229

238-
if (!CurrentEpilog) {
230+
if (!S.getCurrentEpilog()) {
239231
S.getContext().reportError(SMLoc(), "Stray .seh_endepilogue in " +
240232
CurFrame->Function->getName());
241233
return;
242234
}
243235

244236
std::vector<WinEH::Instruction> &Epilog =
245-
CurFrame->EpilogMap[CurrentEpilog].Instructions;
237+
CurFrame->EpilogMap[S.getCurrentEpilog()].Instructions;
246238

247239
unsigned UnwindCode = Win64EH::UOP_End;
248240
if (!Epilog.empty()) {
@@ -256,12 +248,9 @@ void ARMTargetWinCOFFStreamer::emitARMWinCFIEpilogEnd() {
256248
}
257249
}
258250

259-
InEpilogCFI = false;
260251
WinEH::Instruction Inst = WinEH::Instruction(UnwindCode, nullptr, -1, 0);
261-
CurFrame->EpilogMap[CurrentEpilog].Instructions.push_back(Inst);
262-
MCSymbol *Label = S.emitCFILabel();
263-
CurFrame->EpilogMap[CurrentEpilog].End = Label;
264-
CurrentEpilog = nullptr;
252+
CurFrame->EpilogMap[S.getCurrentEpilog()].Instructions.push_back(Inst);
253+
S.emitWinCFIEndEpilogue();
265254
}
266255

267256
void ARMTargetWinCOFFStreamer::emitARMWinCFICustom(unsigned Opcode) {

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,14 +2549,8 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
25492549
--MBBI;
25502550
}
25512551

2552-
// Windows unwinder will not invoke function's exception handler if IP is
2553-
// either in prologue or in epilogue. This behavior causes a problem when a
2554-
// call immediately precedes an epilogue, because the return address points
2555-
// into the epilogue. To cope with that, we insert an epilogue marker here,
2556-
// then replace it with a 'nop' if it ends up immediately after a CALL in the
2557-
// final emitted code.
25582552
if (NeedsWin64CFI && MF.hasWinCFI())
2559-
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue));
2553+
BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_BeginEpilogue));
25602554

25612555
if (!HasFP && NeedsDwarfCFI) {
25622556
MBBI = FirstCSPop;
@@ -2601,6 +2595,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
26012595
// Emit tilerelease for AMX kernel.
26022596
if (X86FI->getAMXProgModel() == AMXProgModelEnum::ManagedRA)
26032597
BuildMI(MBB, Terminator, DL, TII.get(X86::TILERELEASE));
2598+
2599+
if (NeedsWin64CFI && MF.hasWinCFI())
2600+
BuildMI(MBB, Terminator, DL, TII.get(X86::SEH_EndEpilogue));
26042601
}
26052602

26062603
StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF,

llvm/lib/Target/X86/X86InstrCompiler.td

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in {
235235
//===----------------------------------------------------------------------===//
236236
// Pseudo instructions used by unwind info.
237237
//
238-
let isPseudo = 1, SchedRW = [WriteSystem] in {
238+
let isPseudo = 1, isMeta = 1, SchedRW = [WriteSystem] in {
239239
def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg),
240240
"#SEH_PushReg $reg", []>;
241241
def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst),
@@ -252,8 +252,10 @@ let isPseudo = 1, SchedRW = [WriteSystem] in {
252252
"#SEH_PushFrame $mode", []>;
253253
def SEH_EndPrologue : I<0, Pseudo, (outs), (ins),
254254
"#SEH_EndPrologue", []>;
255-
def SEH_Epilogue : I<0, Pseudo, (outs), (ins),
256-
"#SEH_Epilogue", []>;
255+
def SEH_BeginEpilogue : I<0, Pseudo, (outs), (ins),
256+
"#SEH_BeginEpilogue", []>;
257+
def SEH_EndEpilogue : I<0, Pseudo, (outs), (ins),
258+
"#SEH_EndEpilogue", []>;
257259
}
258260

259261
//===----------------------------------------------------------------------===//

llvm/lib/Target/X86/X86MCInstLower.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,14 @@ void X86AsmPrinter::EmitSEHInstruction(const MachineInstr *MI) {
17811781
OutStreamer->emitWinCFIEndProlog();
17821782
break;
17831783

1784+
case X86::SEH_BeginEpilogue:
1785+
OutStreamer->emitWinCFIBeginEpilogue();
1786+
break;
1787+
1788+
case X86::SEH_EndEpilogue:
1789+
OutStreamer->emitWinCFIEndEpilogue();
1790+
break;
1791+
17841792
default:
17851793
llvm_unreachable("expected SEH_ instruction");
17861794
}
@@ -2422,11 +2430,17 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
24222430
case X86::SEH_SetFrame:
24232431
case X86::SEH_PushFrame:
24242432
case X86::SEH_EndPrologue:
2433+
case X86::SEH_EndEpilogue:
24252434
EmitSEHInstruction(MI);
24262435
return;
24272436

2428-
case X86::SEH_Epilogue: {
2437+
case X86::SEH_BeginEpilogue: {
24292438
assert(MF->hasWinCFI() && "SEH_ instruction in function without WinCFI?");
2439+
// Windows unwinder will not invoke function's exception handler if IP is
2440+
// either in prologue or in epilogue. This behavior causes a problem when a
2441+
// call immediately precedes an epilogue, because the return address points
2442+
// into the epilogue. To cope with that, we insert a 'nop' if it ends up
2443+
// immediately after a CALL in the final emitted code.
24302444
MachineBasicBlock::const_iterator MBBI(MI);
24312445
// Check if preceded by a call and emit nop if so.
24322446
for (MBBI = PrevCrossBBInst(MBBI);
@@ -2441,6 +2455,8 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
24412455
break;
24422456
}
24432457
}
2458+
2459+
EmitSEHInstruction(MI);
24442460
return;
24452461
}
24462462
case X86::UBSAN_UD1:

llvm/test/CodeGen/X86/apx/push2-pop2-cfi-seh.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,15 @@ define i32 @csr6_alloc16(ptr %argv) {
142142
; WIN-REF-NEXT: xorl %eax, %eax
143143
; WIN-REF-NEXT: callq *%rax
144144
; WIN-REF-NEXT: nop
145+
; WIN-REF-NEXT: .seh_beginepilogue
145146
; WIN-REF-NEXT: addq $56, %rsp
146147
; WIN-REF-NEXT: popq %rbx
147148
; WIN-REF-NEXT: popq %rbp
148149
; WIN-REF-NEXT: popq %r12
149150
; WIN-REF-NEXT: popq %r13
150151
; WIN-REF-NEXT: popq %r14
151152
; WIN-REF-NEXT: popq %r15
153+
; WIN-REF-NEXT: .seh_endepilogue
152154
; WIN-REF-NEXT: retq
153155
; WIN-REF-NEXT: .seh_endproc
154156
;
@@ -173,11 +175,13 @@ define i32 @csr6_alloc16(ptr %argv) {
173175
; WIN-NEXT: xorl %eax, %eax
174176
; WIN-NEXT: callq *%rax
175177
; WIN-NEXT: nop
178+
; WIN-NEXT: .seh_beginepilogue
176179
; WIN-NEXT: addq $64, %rsp
177180
; WIN-NEXT: pop2 %rbp, %rbx
178181
; WIN-NEXT: pop2 %r13, %r12
179182
; WIN-NEXT: pop2 %r15, %r14
180183
; WIN-NEXT: popq %rcx
184+
; WIN-NEXT: .seh_endepilogue
181185
; WIN-NEXT: retq
182186
; WIN-NEXT: .seh_endproc
183187
;
@@ -202,11 +206,13 @@ define i32 @csr6_alloc16(ptr %argv) {
202206
; WIN-PPX-NEXT: xorl %eax, %eax
203207
; WIN-PPX-NEXT: callq *%rax
204208
; WIN-PPX-NEXT: nop
209+
; WIN-PPX-NEXT: .seh_beginepilogue
205210
; WIN-PPX-NEXT: addq $64, %rsp
206211
; WIN-PPX-NEXT: pop2p %rbp, %rbx
207212
; WIN-PPX-NEXT: pop2p %r13, %r12
208213
; WIN-PPX-NEXT: pop2p %r15, %r14
209214
; WIN-PPX-NEXT: popq %rcx
215+
; WIN-PPX-NEXT: .seh_endepilogue
210216
; WIN-PPX-NEXT: retq
211217
; WIN-PPX-NEXT: .seh_endproc
212218
entry:

0 commit comments

Comments
 (0)