summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinException.cpp17
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinException.h4
-rw-r--r--llvm/test/CodeGen/X86/win64-jumptable.ll60
3 files changed, 71 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 919fc485398..9d7c96a1b8e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -208,8 +208,10 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
}
// Mark 'Sym' as starting our funclet.
- if (shouldEmitMoves || shouldEmitPersonality)
+ if (shouldEmitMoves || shouldEmitPersonality) {
+ CurrentFuncletTextSection = Asm->OutStreamer->getCurrentSectionOnly();
Asm->OutStreamer->EmitWinCFIStartProc(Sym);
+ }
if (shouldEmitPersonality) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
@@ -243,10 +245,6 @@ void WinException::endFunclet() {
if (F->hasPersonalityFn())
Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
- // The .seh_handlerdata directive implicitly switches section, push the
- // current section so that we may return to it.
- Asm->OutStreamer->PushSection();
-
// Emit an UNWIND_INFO struct describing the prologue.
Asm->OutStreamer->EmitWinEHHandlerData();
@@ -265,11 +263,10 @@ void WinException::endFunclet() {
emitCSpecificHandlerTable(MF);
}
- // Switch back to the previous section now that we are done writing to
- // .xdata.
- Asm->OutStreamer->PopSection();
-
- // Emit a .seh_endproc directive to mark the end of the function.
+ // Switch back to the funclet start .text section now that we are done
+ // writing to .xdata, and emit an .seh_endproc directive to mark the end of
+ // the function.
+ Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
Asm->OutStreamer->EmitWinCFIEndProc();
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.h b/llvm/lib/CodeGen/AsmPrinter/WinException.h
index acb30101691..371061c2c2e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.h
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.h
@@ -21,6 +21,7 @@ class Function;
class GlobalValue;
class MachineFunction;
class MCExpr;
+class MCSection;
class Value;
struct WinEHFuncInfo;
@@ -40,6 +41,9 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
/// Pointer to the current funclet entry BB.
const MachineBasicBlock *CurrentFuncletEntry = nullptr;
+ /// The section of the last funclet start.
+ MCSection *CurrentFuncletTextSection = nullptr;
+
void emitCSpecificHandlerTable(const MachineFunction *MF);
void emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
diff --git a/llvm/test/CodeGen/X86/win64-jumptable.ll b/llvm/test/CodeGen/X86/win64-jumptable.ll
new file mode 100644
index 00000000000..6bb9d64c05c
--- /dev/null
+++ b/llvm/test/CodeGen/X86/win64-jumptable.ll
@@ -0,0 +1,60 @@
+; RUN: llc < %s -relocation-model static | FileCheck %s
+
+; FIXME: Remove '-relocation-model static' when it is no longer necessary to
+; trigger the separate .rdata section.
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc19.0.24215"
+
+define void @f(i32 %x) {
+entry:
+ switch i32 %x, label %sw.epilog [
+ i32 0, label %sw.bb
+ i32 1, label %sw.bb1
+ i32 2, label %sw.bb2
+ i32 3, label %sw.bb3
+ ]
+
+sw.bb: ; preds = %entry
+ tail call void @g(i32 0) #2
+ br label %sw.epilog
+
+sw.bb1: ; preds = %entry
+ tail call void @g(i32 1) #2
+ br label %sw.epilog
+
+sw.bb2: ; preds = %entry
+ tail call void @g(i32 2) #2
+ br label %sw.epilog
+
+sw.bb3: ; preds = %entry
+ tail call void @g(i32 3) #2
+ br label %sw.epilog
+
+sw.epilog: ; preds = %entry, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb
+ tail call void @g(i32 10) #2
+ ret void
+}
+
+declare void @g(i32)
+
+; CHECK: .text
+; CHECK: f:
+; CHECK: .seh_proc f
+; CHECK: jmpq *.LJTI0_0
+; CHECK: .LBB0_{{.*}}: # %sw.bb
+; CHECK: .LBB0_{{.*}}: # %sw.bb1
+; CHECK: .LBB0_{{.*}}: # %sw.bb2
+; CHECK: .LBB0_{{.*}}: # %sw.bb3
+; CHECK: callq g
+; CHECK: jmp g # TAILCALL
+; CHECK: .section .rdata,"dr"
+; CHECK: .quad .LBB0_
+; CHECK: .quad .LBB0_
+; CHECK: .quad .LBB0_
+; CHECK: .quad .LBB0_
+; CHECK: .seh_handlerdata
+
+; It's important that we switch back to .text here, not .rdata.
+; CHECK: .text
+; CHECK: .seh_endproc
OpenPOWER on IntegriCloud