[llvm] 9d88ffe - [JITLink] Handle compact-unwind records that depend on DWARF FDEs.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 5 21:10:37 PST 2025


Author: Lang Hames
Date: 2025-02-06T16:10:30+11:00
New Revision: 9d88ffe7f7b4a46d3bcb7bbdf0d7eb037ab5ba04

URL: https://github.com/llvm/llvm-project/commit/9d88ffe7f7b4a46d3bcb7bbdf0d7eb037ab5ba04
DIFF: https://github.com/llvm/llvm-project/commit/9d88ffe7f7b4a46d3bcb7bbdf0d7eb037ab5ba04.diff

LOG: [JITLink] Handle compact-unwind records that depend on DWARF FDEs.

Compact-unwind encodings are more limited than DWARF frame descriptions. For
functions whose frame layout cannot be described by a compact unwind encoding,
the encoding for the function will specify "use DWARF", and the corresponding
unwind-info record will use the low bits of the encoding to point to the FDE
for the function.

We test this with a frame-pointer=none function, since these frame layouts
always triger a fall-back to DWARF on arm64.

Added: 
    llvm/test/ExecutionEngine/Orc/throw-catch-minimal.ll

Modified: 
    llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
    llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
    llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp

Removed: 
    llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
index c306264b6da5d26..c3f883494933562 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
+++ b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
@@ -61,6 +61,14 @@ template <typename CRTPImpl, size_t PtrSize> struct CompactUnwindTraits {
     return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() +
                                                          EncodingFieldOffset);
   }
+
+  static std::optional<uint32_t> encodeDWARFOffset(size_t Delta) {
+    uint32_t Encoded =
+        static_cast<uint32_t>(Delta) & CRTPImpl::DWARFSectionOffsetMask;
+    if (Encoded != Delta)
+      return std::nullopt;
+    return Encoded;
+  }
 };
 
 /// Architecture specific implementation of CompactUnwindManager.
@@ -133,19 +141,22 @@ template <typename CURecTraits> class CompactUnwindManager {
                  << Fn.getName() << "\n";
         });
         continue;
-      } else {
-        LLVM_DEBUG({
-          dbgs() << "    Found record for function ";
-          if (Fn.hasName())
-            dbgs() << Fn.getName();
-          else
-            dbgs() << "<anon @ " << Fn.getAddress() << '>';
-          dbgs() << '\n';
-        });
       }
 
-      bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF(
-          CURecTraits::readEncoding(B->getContent()));
+      uint32_t Encoding = CURecTraits::readEncoding(B->getContent());
+      bool NeedsDWARF = CURecTraits::encodingSpecifiesDWARF(Encoding);
+
+      LLVM_DEBUG({
+        dbgs() << "    Found record for function ";
+        if (Fn.hasName())
+          dbgs() << Fn.getName();
+        else
+          dbgs() << "<anon @ " << Fn.getAddress() << '>';
+        dbgs() << ": encoding = " << formatv("{0:x}", Encoding);
+        if (NeedsDWARF)
+          dbgs() << " (needs DWARF)";
+        dbgs() << "\n";
+      });
 
       auto &CURecSym =
           G.addAnonymousSymbol(*B, 0, CURecTraits::Size, false, false);
@@ -170,7 +181,7 @@ template <typename CURecTraits> class CompactUnwindManager {
           KeepAliveAlreadyPresent = true;
           if (NeedsDWARF) {
             LLVM_DEBUG({
-              dbgs() << "      Needs DWARF: adding keep-alive edge to FDE at "
+              dbgs() << "      Adding keep-alive edge to FDE at "
                      << FDE.getAddress() << "\n";
             });
             B->addEdge(Edge::KeepAlive, 0, FDE, 0);
@@ -595,8 +606,24 @@ template <typename CURecTraits> class CompactUnwindManager {
             ", delta to function at " + formatv("{0:x}", R.Fn->getAddress()) +
             " exceeds 32 bits");
 
+      auto Encoding = R.Encoding;
+
+      if (LLVM_UNLIKELY(CURecTraits::encodingSpecifiesDWARF(R.Encoding))) {
+        if (!EHFrameBase)
+          EHFrameBase = SectionRange(R.FDE->getSection()).getStart();
+        auto FDEDelta = R.FDE->getAddress() - EHFrameBase;
+
+        if (auto EncodedFDEDelta = CURecTraits::encodeDWARFOffset(FDEDelta))
+          Encoding |= *EncodedFDEDelta;
+        else
+          return make_error<JITLinkError>(
+              "In " + G.getName() + " " + UnwindInfoSectionName +
+              ", cannot encode delta " + formatv("{0:x}", FDEDelta) +
+              " to FDE at " + formatv("{0:x}", R.FDE->getAddress()));
+      }
+
       cantFail(W.writeInteger<uint32_t>(FnDelta));
-      cantFail(W.writeInteger<uint32_t>(R.Encoding));
+      cantFail(W.writeInteger<uint32_t>(Encoding));
 
       ++RecordIdx;
     }
@@ -639,6 +666,7 @@ template <typename CURecTraits> class CompactUnwindManager {
   StringRef UnwindInfoSectionName;
   StringRef EHFrameSectionName;
   Symbol *CompactUnwindBase = nullptr;
+  orc::ExecutorAddr EHFrameBase;
 
   size_t NumLSDAs = 0;
   size_t NumSecondLevelPages = 0;

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index 4860db4f5eb37c6..3af0c0cdeb7c335 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -637,6 +637,7 @@ struct CompactUnwindTraits_MachO_arm64
   constexpr static endianness Endianness = endianness::little;
 
   constexpr static uint32_t EncodingModeMask = 0x0f000000;
+  constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;
 
   using GOTManager = aarch64::GOTTableManager;
 

diff  --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index d56dfdc07636dfe..bb5f3ab7ed43cd5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -512,6 +512,7 @@ struct CompactUnwindTraits_MachO_x86_64
   constexpr static endianness Endianness = endianness::little;
 
   constexpr static uint32_t EncodingModeMask = 0x0f000000;
+  constexpr static uint32_t DWARFSectionOffsetMask = 0x00ffffff;
 
   using GOTManager = x86_64::GOTTableManager;
 

diff  --git a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/Orc/throw-catch-minimal.ll
similarity index 100%
rename from llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
rename to llvm/test/ExecutionEngine/Orc/throw-catch-minimal.ll


        


More information about the llvm-commits mailing list