[clang] [llvm] [MC] Emit a jump table size section (PR #101962)

Nabeel Omer via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 22 03:25:25 PDT 2024


https://github.com/omern1 updated https://github.com/llvm/llvm-project/pull/101962

>From 14f3cb82f0d7e69261bd7e1317bd66392e9a2c2b Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Mon, 5 Aug 2024 11:50:18 +0100
Subject: [PATCH 1/9] [MC] Emit a jump table size section

This patch will make LLVM emit a jump table size section containing
tuples of (jump table address, entry count) in object files.
This section is useful for tools that need to statically reconstruct
the control flow of executables.

The name of the new section is .debug_llvm_jump_table_sizes
because that makes both llvm-strip and GNU strip remove it.

At the moment this is only enabled by default for the PS5 target.
---
 clang/lib/Driver/ToolChains/PS4CPU.cpp        |  8 ++
 clang/test/Driver/ps4-ps5-toolchain.c         |  5 +
 llvm/docs/Extensions.rst                      |  6 ++
 llvm/include/llvm/BinaryFormat/ELF.h          |  1 +
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    | 26 +++++
 llvm/lib/MC/MCParser/ELFAsmParser.cpp         |  2 +
 llvm/lib/MC/MCSectionELF.cpp                  |  2 +
 llvm/lib/Object/ELF.cpp                       |  1 +
 .../CodeGen/X86/jump-table-size-section.ll    | 97 +++++++++++++++++++
 9 files changed, 148 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/jump-table-size-section.ll

diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index a9e612c44da06a..f9a9e995fff8e2 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -265,6 +265,8 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(D.getLTOMode() == LTOK_Thin ? "--lto=thin"
                                                   : "--lto=full");
 
+  AddLTOFlag("-emit-jump-table-sizes-section");
+
   if (UseJMC)
     AddLTOFlag("-enable-jmc-instrument");
 
@@ -483,6 +485,12 @@ void toolchains::PS4PS5Base::addClangTargetOptions(
     else
       CC1Args.push_back("-fvisibility-externs-nodllstorageclass=keep");
   }
+
+  // Enable jump table sizes section for PS5.
+  if (getTriple().isPS5()) {
+    CC1Args.push_back("-mllvm");
+    CC1Args.push_back("-emit-jump-table-sizes-section");
+  }
 }
 
 // PS4 toolchain.
diff --git a/clang/test/Driver/ps4-ps5-toolchain.c b/clang/test/Driver/ps4-ps5-toolchain.c
index 444e9df24714bd..c9987c2b5758b3 100644
--- a/clang/test/Driver/ps4-ps5-toolchain.c
+++ b/clang/test/Driver/ps4-ps5-toolchain.c
@@ -11,3 +11,8 @@
 // RUN: %clang %s -### -target x86_64-sie-ps5 -flto 2>&1 | FileCheck %s --check-prefix=LTO
 // LTO-NOT: error:
 // LTO-NOT: unable to pass LLVM bit-code
+
+// Verify that the jump table sizes section is enabled.
+// RUN: %clang %s -target x86_64-sie-ps5 -### 2>&1 | FileCheck -check-prefix=JUMPTABLESIZES %s
+// JUMPTABLESIZES: "-mllvm" "-emit-jump-table-sizes-section"
+// JUMPTABLESIZES: "-plugin-opt=-emit-jump-table-sizes-section"
diff --git a/llvm/docs/Extensions.rst b/llvm/docs/Extensions.rst
index 74ca8cb0aa6879..0e209f3fe5cc0d 100644
--- a/llvm/docs/Extensions.rst
+++ b/llvm/docs/Extensions.rst
@@ -554,6 +554,12 @@ time. This section is generated when the compiler enables fat LTO. This section
 has the ``SHF_EXCLUDE`` flag so that it is stripped from the final executable
 or shared library.
 
+``SHT_LLVM_JT_SIZES`` Section (Jump table addresses and sizes)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This section stores pairs of (jump table address, number of entries).
+This information is useful for tools that need to statically reconstruct
+the control flow of executables.
+
 CodeView-Dependent
 ------------------
 
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index fb39bb4b10b377..7bec01688783d3 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1121,6 +1121,7 @@ enum : unsigned {
   SHT_LLVM_BB_ADDR_MAP = 0x6fff4c0a,        // LLVM Basic Block Address Map.
   SHT_LLVM_OFFLOADING = 0x6fff4c0b,         // LLVM device offloading data.
   SHT_LLVM_LTO = 0x6fff4c0c,                // .llvm.lto for fat LTO.
+  SHT_LLVM_JT_SIZES = 0x6fff4c0d,           // LLVM jump tables sizes.
   // Android's experimental support for SHT_RELR sections.
   // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
   SHT_ANDROID_RELR = 0x6fffff00,   // Relocation entries; only offsets.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index b64fe83959eb18..05624d2728bfdb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -107,6 +107,7 @@
 #include "llvm/Pass.h"
 #include "llvm/Remarks/RemarkStreamer.h"
 #include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
@@ -155,6 +156,11 @@ static cl::bits<PGOMapFeaturesEnum> PgoAnalysisMapFeatures(
         "Enable extended information within the SHT_LLVM_BB_ADDR_MAP that is "
         "extracted from PGO related analysis."));
 
+static cl::opt<bool> EmitJumpTableSizesSection(
+    "emit-jump-table-sizes-section",
+    cl::desc("Emit a section containing jump table addresses and sizes"),
+    cl::Hidden, cl::init(false));
+
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
 char AsmPrinter::ID = 0;
@@ -2764,6 +2770,26 @@ void AsmPrinter::emitJumpTableInfo() {
     for (const MachineBasicBlock *MBB : JTBBs)
       emitJumpTableEntry(MJTI, MBB, JTI);
   }
+
+  if (EmitJumpTableSizesSection && !JT.empty()) {
+    MCSymbolELF *LinkedToSym = cast<MCSymbolELF>(CurrentFnSym);
+    int Flags = F.hasComdat() ? ELF::SHF_GROUP : 0;
+    StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
+
+    MCSection *JumpTableSizesSection = OutContext.getELFSection(
+        ".debug_llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName,
+        F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
+
+    OutStreamer->switchSection(JumpTableSizesSection);
+
+    for (unsigned JTI = 0, E = JT.size(); JTI != E; ++JTI) {
+      const std::vector<MachineBasicBlock *> &JTBBs = JT[JTI].MBBs;
+      OutStreamer->emitSymbolValue(GetJTISymbol(JTI),
+                                   TM.getProgramPointerSize());
+      OutStreamer->emitIntValue(JTBBs.size(), TM.getProgramPointerSize());
+    }
+  }
+
   if (!JTInDiffSection)
     OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
 }
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index e8a22d3defd6e8..c4536441665fa0 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -677,6 +677,8 @@ bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
       Type = ELF::SHT_LLVM_OFFLOADING;
     else if (TypeName == "llvm_lto")
       Type = ELF::SHT_LLVM_LTO;
+    else if (TypeName == "llvm_jt_sizes")
+      Type = ELF::SHT_LLVM_JT_SIZES;
     else if (TypeName.getAsInteger(0, Type))
       return TokError("unknown section type");
   }
diff --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp
index 5cd6590fb626d3..25e62b70b5e2a0 100644
--- a/llvm/lib/MC/MCSectionELF.cpp
+++ b/llvm/lib/MC/MCSectionELF.cpp
@@ -172,6 +172,8 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     OS << "llvm_offloading";
   else if (Type == ELF::SHT_LLVM_LTO)
     OS << "llvm_lto";
+  else if (Type == ELF::SHT_LLVM_JT_SIZES)
+    OS << "llvm_jt_sizes";
   else
     OS << "0x" << Twine::utohexstr(Type);
 
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index e47a40b8715dd5..c66736fb2c9194 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -319,6 +319,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_BB_ADDR_MAP);
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_OFFLOADING);
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LTO);
+    STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_JT_SIZES)
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
diff --git a/llvm/test/CodeGen/X86/jump-table-size-section.ll b/llvm/test/CodeGen/X86/jump-table-size-section.ll
new file mode 100644
index 00000000000000..4a259aecd72b61
--- /dev/null
+++ b/llvm/test/CodeGen/X86/jump-table-size-section.ll
@@ -0,0 +1,97 @@
+; RUN: llc %s -o - -emit-jump-table-sizes-section -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=CHECK %s
+; RUN: llc %s -o - -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOFLAG %s
+
+; This test verifies the jump table size section. Currently only enabled by default on the PS5 target.
+
+$foo1 = comdat any
+
+; Ensure proper comdat handling.
+define void @foo1(i32 %x, ptr %to) comdat {
+
+; CHECK-LABEL: foo1
+; CHECK:      .section        .debug_llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
+; CHECK-NEXT: .quad   .LJTI0_0
+; CHECK-NEXT: .quad   6
+
+; NOFLAG-LABEL: foo1
+; NOFLAG-NOT: .section        .debug_llvm_jump_table_sizes
+
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb2
+    i32 3, label %bb3
+    i32 4, label %bb4
+    i32 5, label %bb4
+  ]
+bb0:
+  store i32 0, ptr %to
+  br label %exit
+bb1:
+  store i32 1, ptr %to
+  br label %exit
+bb2:
+  store i32 2, ptr %to
+  br label %exit
+bb3:
+  store i32 3, ptr %to
+  br label %exit
+bb4:
+  store i32 4, ptr %to
+  br label %exit
+exit:
+  ret void
+default:
+  unreachable
+}
+
+define void @foo2(i32 %x, ptr %to) {
+
+; CHECK-LABEL: foo2
+; CHECK:      .section        .debug_llvm_jump_table_sizes
+; CHECK-NEXT: .quad   .LJTI1_0
+; CHECK-NEXT: .quad   5
+
+; NOFLAG-LABEL: foo2
+; NOFLAG-NOT: .section        .debug_llvm_jump_table_sizes
+
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb2
+    i32 3, label %bb3
+    i32 4, label %bb4
+  ]
+bb0:
+  store i32 0, ptr %to
+  br label %exit
+bb1:
+  store i32 1, ptr %to
+  br label %exit
+bb2:
+  store i32 2, ptr %to
+  br label %exit
+bb3:
+  store i32 3, ptr %to
+  br label %exit
+bb4:
+  store i32 4, ptr %to
+  br label %exit
+exit:
+  ret void
+default:
+  unreachable
+}
+
+; Ensure that the section isn't produced if there is no jump table.
+
+define void @foo3(i32 %x, ptr %to) {
+
+; CHECK-LABEL:    foo3
+; CHECK-NOT:      .section        .debug_llvm_jump_table_sizes
+
+exit:
+  ret void
+}

>From 450ade1d9523386c192f2ec05391e187018c9d7f Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Mon, 5 Aug 2024 12:29:19 +0100
Subject: [PATCH 2/9] Fix formatting

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 05624d2728bfdb..50a89bc70a45e5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2777,8 +2777,8 @@ void AsmPrinter::emitJumpTableInfo() {
     StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
 
     MCSection *JumpTableSizesSection = OutContext.getELFSection(
-        ".debug_llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName,
-        F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
+        ".debug_llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0,
+        GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
 
     OutStreamer->switchSection(JumpTableSizesSection);
 

>From 5ae406c94e0f1e4a872285e9f8f1feff9498e2c2 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Mon, 5 Aug 2024 13:10:07 +0100
Subject: [PATCH 3/9] Add more squiggles

---
 llvm/docs/Extensions.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/docs/Extensions.rst b/llvm/docs/Extensions.rst
index 0e209f3fe5cc0d..abc34bc3202c09 100644
--- a/llvm/docs/Extensions.rst
+++ b/llvm/docs/Extensions.rst
@@ -555,7 +555,7 @@ has the ``SHF_EXCLUDE`` flag so that it is stripped from the final executable
 or shared library.
 
 ``SHT_LLVM_JT_SIZES`` Section (Jump table addresses and sizes)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 This section stores pairs of (jump table address, number of entries).
 This information is useful for tools that need to statically reconstruct
 the control flow of executables.

>From 0fe0d9d8577ebae62b7ea9ed2854bd22f8ac42e9 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Wed, 7 Aug 2024 13:48:46 +0100
Subject: [PATCH 4/9] Restrict to ELF

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 50a89bc70a45e5..e8438dfad59f27 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2771,7 +2771,7 @@ void AsmPrinter::emitJumpTableInfo() {
       emitJumpTableEntry(MJTI, MBB, JTI);
   }
 
-  if (EmitJumpTableSizesSection && !JT.empty()) {
+  if (EmitJumpTableSizesSection && TM.getTargetTriple().isOSBinFormatELF() && !JT.empty()) {
     MCSymbolELF *LinkedToSym = cast<MCSymbolELF>(CurrentFnSym);
     int Flags = F.hasComdat() ? ELF::SHF_GROUP : 0;
     StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";

>From 992c71fc14515eda8547ac9dd239aeb39e561a79 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Thu, 8 Aug 2024 10:56:55 +0100
Subject: [PATCH 5/9] Fix formatting

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index e8438dfad59f27..6e9e4d68c5aba0 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2771,7 +2771,8 @@ void AsmPrinter::emitJumpTableInfo() {
       emitJumpTableEntry(MJTI, MBB, JTI);
   }
 
-  if (EmitJumpTableSizesSection && TM.getTargetTriple().isOSBinFormatELF() && !JT.empty()) {
+  if (EmitJumpTableSizesSection && TM.getTargetTriple().isOSBinFormatELF() &&
+      !JT.empty()) {
     MCSymbolELF *LinkedToSym = cast<MCSymbolELF>(CurrentFnSym);
     int Flags = F.hasComdat() ? ELF::SHF_GROUP : 0;
     StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";

>From 8084241638d25998903d102910d6290414997cfb Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Tue, 20 Aug 2024 13:49:23 +0100
Subject: [PATCH 6/9] Remove `.debug_` prefix

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 6e9e4d68c5aba0..b86ae4564060f4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2778,7 +2778,7 @@ void AsmPrinter::emitJumpTableInfo() {
     StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
 
     MCSection *JumpTableSizesSection = OutContext.getELFSection(
-        ".debug_llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0,
+        ".llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0,
         GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
 
     OutStreamer->switchSection(JumpTableSizesSection);

>From 5d3dd1cff4916a4e67d5c23ee301ac92d31b37c7 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Tue, 20 Aug 2024 13:51:32 +0100
Subject: [PATCH 7/9] Update test

---
 llvm/test/CodeGen/X86/jump-table-size-section.ll | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/test/CodeGen/X86/jump-table-size-section.ll b/llvm/test/CodeGen/X86/jump-table-size-section.ll
index 4a259aecd72b61..0eb23d54b8b0cd 100644
--- a/llvm/test/CodeGen/X86/jump-table-size-section.ll
+++ b/llvm/test/CodeGen/X86/jump-table-size-section.ll
@@ -9,12 +9,12 @@ $foo1 = comdat any
 define void @foo1(i32 %x, ptr %to) comdat {
 
 ; CHECK-LABEL: foo1
-; CHECK:      .section        .debug_llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
+; CHECK:      .section        .llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
 ; CHECK-NEXT: .quad   .LJTI0_0
 ; CHECK-NEXT: .quad   6
 
 ; NOFLAG-LABEL: foo1
-; NOFLAG-NOT: .section        .debug_llvm_jump_table_sizes
+; NOFLAG-NOT: .section        .llvm_jump_table_sizes
 
 entry:
   switch i32 %x, label %default [
@@ -49,12 +49,12 @@ default:
 define void @foo2(i32 %x, ptr %to) {
 
 ; CHECK-LABEL: foo2
-; CHECK:      .section        .debug_llvm_jump_table_sizes
+; CHECK:      .section        .llvm_jump_table_sizes
 ; CHECK-NEXT: .quad   .LJTI1_0
 ; CHECK-NEXT: .quad   5
 
 ; NOFLAG-LABEL: foo2
-; NOFLAG-NOT: .section        .debug_llvm_jump_table_sizes
+; NOFLAG-NOT: .section        .llvm_jump_table_sizes
 
 entry:
   switch i32 %x, label %default [
@@ -90,7 +90,7 @@ default:
 define void @foo3(i32 %x, ptr %to) {
 
 ; CHECK-LABEL:    foo3
-; CHECK-NOT:      .section        .debug_llvm_jump_table_sizes
+; CHECK-NOT:      .section        .llvm_jump_table_sizes
 
 exit:
   ret void

>From d42fedf8617f6755b189bd1d700e0da139c8ccd7 Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Tue, 20 Aug 2024 13:57:01 +0100
Subject: [PATCH 8/9] Fix formatting

---
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index b86ae4564060f4..9fe88ac48b3de3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2778,8 +2778,8 @@ void AsmPrinter::emitJumpTableInfo() {
     StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
 
     MCSection *JumpTableSizesSection = OutContext.getELFSection(
-        ".llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0,
-        GroupName, F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
+        ".llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName,
+        F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
 
     OutStreamer->switchSection(JumpTableSizesSection);
 

>From d71791b25b48338842641cbb1566a20e53a6dedd Mon Sep 17 00:00:00 2001
From: Nabeel Omer <Nabeel.Omer at sony.com>
Date: Thu, 22 Aug 2024 11:24:39 +0100
Subject: [PATCH 9/9] Add support for COFF

---
 llvm/include/llvm/CodeGen/AsmPrinter.h        |   4 +
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  63 +++++---
 .../CodeGen/X86/jump-table-size-section.ll    | 141 ++++++++++++++++--
 3 files changed, 177 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 36d1b479738704..c9a88d7b1c015c 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -894,6 +894,10 @@ class AsmPrinter : public MachineFunctionPass {
 
   void emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
                           const MachineBasicBlock *MBB, unsigned uid) const;
+
+  void emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
+                                 const Function &F) const;
+
   void emitLLVMUsedList(const ConstantArray *InitList);
   /// Emit llvm.ident metadata in an '.ident' directive.
   void emitModuleIdents(Module &M);
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 9fe88ac48b3de3..578dc445c772c9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -99,6 +99,7 @@
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolCOFF.h"
 #include "llvm/MC/MCSymbolELF.h"
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/MCValue.h"
@@ -2771,28 +2772,56 @@ void AsmPrinter::emitJumpTableInfo() {
       emitJumpTableEntry(MJTI, MBB, JTI);
   }
 
-  if (EmitJumpTableSizesSection && TM.getTargetTriple().isOSBinFormatELF() &&
-      !JT.empty()) {
-    MCSymbolELF *LinkedToSym = cast<MCSymbolELF>(CurrentFnSym);
-    int Flags = F.hasComdat() ? ELF::SHF_GROUP : 0;
-    StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
+  if (EmitJumpTableSizesSection)
+    emitJumpTableSizesSection(MJTI, F);
 
-    MCSection *JumpTableSizesSection = OutContext.getELFSection(
-        ".llvm_jump_table_sizes", ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName,
-        F.hasComdat(), MCSection::NonUniqueID, LinkedToSym);
+  if (!JTInDiffSection)
+    OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+}
 
-    OutStreamer->switchSection(JumpTableSizesSection);
+void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
+                                           const Function &F) const {
+  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
 
-    for (unsigned JTI = 0, E = JT.size(); JTI != E; ++JTI) {
-      const std::vector<MachineBasicBlock *> &JTBBs = JT[JTI].MBBs;
-      OutStreamer->emitSymbolValue(GetJTISymbol(JTI),
-                                   TM.getProgramPointerSize());
-      OutStreamer->emitIntValue(JTBBs.size(), TM.getProgramPointerSize());
-    }
+  if (JT.empty())
+    return;
+
+  StringRef GroupName = F.hasComdat() ? F.getComdat()->getName() : "";
+  MCSection *JumpTableSizesSection = nullptr;
+  StringRef sectionName = ".llvm_jump_table_sizes";
+
+  if (TM.getTargetTriple().isOSBinFormatELF()) {
+    MCSymbolELF *LinkedToSym = dyn_cast<MCSymbolELF>(CurrentFnSym);
+    int Flags = F.hasComdat() ? ELF::SHF_GROUP : 0;
+
+    JumpTableSizesSection = OutContext.getELFSection(
+        sectionName, ELF::SHT_LLVM_JT_SIZES, Flags, 0, GroupName, F.hasComdat(),
+        MCSection::NonUniqueID, LinkedToSym);
+  } else if (TM.getTargetTriple().isOSBinFormatCOFF()) {
+    if (F.hasComdat()) {
+      MCSymbolCOFF *LinkedToSym = dyn_cast<MCSymbolCOFF>(CurrentFnSym);
+
+      JumpTableSizesSection = OutContext.getCOFFSection(
+          sectionName,
+          COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
+              COFF::IMAGE_SCN_LNK_COMDAT | COFF::IMAGE_SCN_MEM_DISCARDABLE,
+          F.getComdat()->getName(), COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE);
+    } else
+      JumpTableSizesSection = OutContext.getCOFFSection(
+          sectionName, COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                           COFF::IMAGE_SCN_MEM_READ |
+                           COFF::IMAGE_SCN_MEM_DISCARDABLE);
+  } else {
+    return;
   }
 
-  if (!JTInDiffSection)
-    OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
+  OutStreamer->switchSection(JumpTableSizesSection);
+
+  for (unsigned JTI = 0, E = JT.size(); JTI != E; ++JTI) {
+    const std::vector<MachineBasicBlock *> &JTBBs = JT[JTI].MBBs;
+    OutStreamer->emitSymbolValue(GetJTISymbol(JTI), TM.getProgramPointerSize());
+    OutStreamer->emitIntValue(JTBBs.size(), TM.getProgramPointerSize());
+  }
 }
 
 /// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
diff --git a/llvm/test/CodeGen/X86/jump-table-size-section.ll b/llvm/test/CodeGen/X86/jump-table-size-section.ll
index 0eb23d54b8b0cd..c0b57e96d56b02 100644
--- a/llvm/test/CodeGen/X86/jump-table-size-section.ll
+++ b/llvm/test/CodeGen/X86/jump-table-size-section.ll
@@ -1,5 +1,14 @@
-; RUN: llc %s -o - -emit-jump-table-sizes-section -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=CHECK %s
-; RUN: llc %s -o - -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOFLAG %s
+; RUN: llc %s -o - -mtriple x86_64-sie-ps5 -emit-jump-table-sizes-section -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=PS5-CHECK %s
+; RUN: llc %s -o - -mtriple x86_64-sie-ps5 -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOFLAG %s
+; RUN: llc %s -o - -mtriple x86_64-sie-ps5 -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOTABLE %s
+
+; RUN: llc %s -o - -mtriple x86_64-unknown-linux-gnu -emit-jump-table-sizes-section -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=ELF-CHECK %s
+; RUN: llc %s -o - -mtriple x86_64-unknown-linux-gnu -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOFLAG %s
+; RUN: llc %s -o - -mtriple x86_64-unknown-linux-gnu -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOTABLE %s
+
+; RUN: llc %s -o - -mtriple x86_64-pc-windows-msvc -emit-jump-table-sizes-section -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=COFF-CHECK %s
+; RUN: llc %s -o - -mtriple x86_64-pc-windows-msvc -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOFLAG %s
+; RUN: llc %s -o - -mtriple x86_64-pc-windows-msvc -verify-machineinstrs --relocation-model=pic | FileCheck --check-prefix=NOTABLE %s
 
 ; This test verifies the jump table size section. Currently only enabled by default on the PS5 target.
 
@@ -8,10 +17,20 @@ $foo1 = comdat any
 ; Ensure proper comdat handling.
 define void @foo1(i32 %x, ptr %to) comdat {
 
-; CHECK-LABEL: foo1
-; CHECK:      .section        .llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
-; CHECK-NEXT: .quad   .LJTI0_0
-; CHECK-NEXT: .quad   6
+; PS5-CHECK-LABEL: foo1
+; PS5-CHECK:       .section        .llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
+; PS5-CHECK-NEXT: .quad   .LJTI0_0
+; PS5-CHECK-NEXT: .quad   6
+
+; ELF-CHECK-LABEL: foo1
+; ELF-CHECK:       .section        .llvm_jump_table_sizes,"G", at llvm_jt_sizes,foo1,comdat
+; ELF-CHECK-NEXT: .quad   .LJTI0_0
+; ELF-CHECK-NEXT: .quad   6
+
+; COFF-CHECK-LABEL: foo1
+; COFF-CHECK:      .section         .llvm_jump_table_sizes,"drD",associative,foo1
+; COFF-CHECK-NEXT: .quad   .LJTI0_0
+; COFF-CHECK-NEXT: .quad   6
 
 ; NOFLAG-LABEL: foo1
 ; NOFLAG-NOT: .section        .llvm_jump_table_sizes
@@ -48,13 +67,23 @@ default:
 
 define void @foo2(i32 %x, ptr %to) {
 
-; CHECK-LABEL: foo2
-; CHECK:      .section        .llvm_jump_table_sizes
-; CHECK-NEXT: .quad   .LJTI1_0
-; CHECK-NEXT: .quad   5
+; PS5-CHECK-LABEL:    foo2
+; PS5-CHECK:          .section .llvm_jump_table_sizes,"", at llvm_jt_sizes
+; PS5-CHECK-NEXT:     .quad .LJTI1_0
+; PS5-CHECK-NEXT:     .quad   5
 
-; NOFLAG-LABEL: foo2
-; NOFLAG-NOT: .section        .llvm_jump_table_sizes
+; ELF-CHECK-LABEL:    foo2
+; ELF-CHECK:          .section .llvm_jump_table_sizes,"", at llvm_jt_sizes
+; ELF-CHECK-NEXT:     .quad .LJTI1_0
+; ELF-CHECK-NEXT:     .quad   5
+
+; COFF-CHECK-LABEL:   foo2
+; COFF-CHECK:         .section         .llvm_jump_table_sizes,"drD"
+; COFF-CHECK-NEXT:    .quad .LJTI1_0
+; COFF-CHECK-NEXT:    .quad   5
+
+; NOFLAG-LABEL:       foo1
+; NOFLAG-NOT:         .section        .llvm_jump_table_sizes
 
 entry:
   switch i32 %x, label %default [
@@ -89,9 +118,93 @@ default:
 
 define void @foo3(i32 %x, ptr %to) {
 
-; CHECK-LABEL:    foo3
-; CHECK-NOT:      .section        .llvm_jump_table_sizes
+; NOTABLE-LABEL:    foo3
+; NOTABLE-NOT:      .section        .llvm_jump_table_sizes
 
 exit:
   ret void
 }
+
+; Ensure we can deal with nested jump tables.
+
+define void @nested(i32 %x, i32 %y, ptr %to) {
+
+; PS5-CHECK-LABEL:    nested
+; PS5-CHECK:          .section .llvm_jump_table_sizes,"", at llvm_jt_sizes
+; PS5-CHECK-NEXT:     .quad .LJTI3_0
+; PS5-CHECK-NEXT:     .quad   5
+; PS5-CHECK-NEXT:     .quad .LJTI3_1
+; PS5-CHECK-NEXT:     .quad 6
+
+; ELF-CHECK-LABEL:    nested
+; ELF-CHECK:          .section .llvm_jump_table_sizes,"", at llvm_jt_sizes
+; ELF-CHECK-NEXT:     .quad .LJTI3_0
+; ELF-CHECK-NEXT:     .quad   5
+; ELF-CHECK-NEXT:     .quad .LJTI3_1
+; ELF-CHECK-NEXT:     .quad 6
+
+; COFF-CHECK-LABEL:   nested
+; COFF-CHECK:         .section         .llvm_jump_table_sizes,"drD"
+; COFF-CHECK-NEXT:     .quad .LJTI3_0
+; COFF-CHECK-NEXT:     .quad   5
+; COFF-CHECK-NEXT:     .quad .LJTI3_1
+; COFF-CHECK-NEXT:     .quad 6
+
+; NOFLAG-LABEL:       nested
+; NOFLAG-NOT:         .section        .llvm_jump_table_sizes
+
+entry:
+  switch i32 %x, label %default [
+    i32 0, label %bb0
+    i32 1, label %bb1
+    i32 2, label %bb2
+    i32 3, label %bb3
+    i32 4, label %bb4
+  ]
+bb0:
+  store i32 0, ptr %to
+  br label %exit
+bb1:
+  store i32 1, ptr %to
+  br label %exit
+bb2:
+  store i32 2, ptr %to
+  br label %exit
+bb3:
+  store i32 3, ptr %to
+  br label %exit
+bb4:
+  switch i32 %y, label %default [
+    i32 1, label %bb5
+    i32 2, label %bb6
+    i32 3, label %bb7
+    i32 4, label %bb8
+    i32 5, label %bb9
+    i32 6, label %bb10
+  ]
+  br label %exit2
+bb5:
+  store i32 4, ptr %to
+  br label %exit
+bb6:
+  store i32 4, ptr %to
+  br label %exit
+bb7:
+  store i32 4, ptr %to
+  br label %exit
+bb8:
+  store i32 4, ptr %to
+  br label %exit
+bb9:
+  store i32 4, ptr %to
+  br label %exit
+bb10:
+  store i32 4, ptr %to
+  br label %exit
+exit:
+  ret void
+exit2:
+  ret void
+default:
+  unreachable
+}
\ No newline at end of file



More information about the llvm-commits mailing list