Skip to content

Commit eae6d6d

Browse files
committed
Re-reapply "[ORC] Enable JIT support for the compact-unwind..." with fixes.
Re-enables compact-unwind support in JITLink, which was reverted in b04847b due to buildbot failures. The underlying cause for the failures on the buildbots was the lack of compact-unwind registration support on older Darwin OSes. Since the CompactUnwindManager pass now removes eh-frames by default we were left with unwind-info that could not be registered. On x86-64, where eh-frame info is produced by default the solution is to fall back to using eh-frames. On arm64 we simply can't support exceptions on older OSes. This patch updates the EHFrameRegistrationPlugin to remove the compact-unwind section (__LD,__compact_unwind) when installed, forcing use of eh-frames when the EHFrameRegistrationPlugin is used. In LLJIT, the EHFrameRegistrationPlugin continues to be used for all non-Darwin platform, and will be added on Darwin platforms when the a CompactUnwindRegistrationPlugin instance can't be created (e.g. due to missing support for compact-unwind info registration). The lit.cfg.py script is updated to check whether the host OSes default unwind info supports JIT registration, allowing tests to be disabled for older Darwin OSes on arm64.
1 parent 84b0c12 commit eae6d6d

30 files changed

+1606
-172
lines changed

clang/test/Interpreter/simple-exception.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// clang-format off
22
// UNSUPPORTED: system-aix
3-
// XFAIL for arm and arm64, or running on Windows.
4-
// XFAIL: target=arm{{.*}}, system-windows
3+
// XFAIL for arm, or running on Windows.
4+
// XFAIL: target=arm-{{.*}}, target=armv{{.*}}, system-windows
55
// RUN: cat %s | clang-repl | FileCheck %s
66

77
// Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter

compiler-rt/lib/orc/macho_platform.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,12 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections(
557557
return make_error<StringError>(ErrStream.str());
558558
}
559559

560+
ORC_RT_DEBUG({
561+
printdbg(" UnwindInfo: %s, UseCallbackStyleUnwindInfo: %s\n",
562+
UnwindInfo ? "true" : "false",
563+
UseCallbackStyleUnwindInfo ? "true" : "false");
564+
});
565+
560566
if (UnwindInfo && UseCallbackStyleUnwindInfo) {
561567
ORC_RT_DEBUG({
562568
printdbg(" Registering new-style unwind info for:\n"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clangxx -c -o %t %s
2+
// RUN: %llvm_jitlink -slab-allocate=20Mb %t
3+
//
4+
// REQUIRES: system-darwin && host-arch-compatible
5+
6+
int main(int argc, char *argv[]) {
7+
try {
8+
throw 42;
9+
} catch (int E) {
10+
return 42 - E;
11+
}
12+
return 1;
13+
}

llvm/include/llvm/ExecutionEngine/Orc/Core.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,13 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
12041204

12051205
JITDylib(ExecutionSession &ES, std::string Name);
12061206

1207-
std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
1208-
IL_removeTracker(ResourceTracker &RT);
1207+
struct RemoveTrackerResult {
1208+
AsynchronousSymbolQuerySet QueriesToFail;
1209+
std::shared_ptr<SymbolDependenceMap> FailedSymbols;
1210+
std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;
1211+
};
1212+
1213+
RemoveTrackerResult IL_removeTracker(ResourceTracker &RT);
12091214

12101215
void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
12111216

llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
2121
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
2222
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
23+
#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h"
2324
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
2425
#include "llvm/Support/DynamicLibrary.h"
2526
#include "llvm/Support/MSVCErrorWorkarounds.h"
@@ -507,6 +508,9 @@ class SelfExecutorProcessControl : public ExecutorProcessControl,
507508
SymbolLookupCompleteFn F) override;
508509

509510
std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
511+
#ifdef __APPLE__
512+
std::unique_ptr<UnwindInfoManager> UnwindInfoMgr;
513+
#endif // __APPLE__
510514
char GlobalManglingPrefix = 0;
511515
};
512516

llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace orc {
2525
extern StringRef MachODataCommonSectionName;
2626
extern StringRef MachODataDataSectionName;
2727
extern StringRef MachOEHFrameSectionName;
28+
extern StringRef MachOCompactUnwindSectionName;
2829
extern StringRef MachOCStringSectionName;
2930
extern StringRef MachOModInitFuncSectionName;
3031
extern StringRef MachOObjCCatListSectionName;

llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,15 @@ using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddr,
8888
using SPSRunAsVoidFunctionSignature = int32_t(shared::SPSExecutorAddr);
8989
using SPSRunAsIntFunctionSignature = int32_t(shared::SPSExecutorAddr, int32_t);
9090
} // end namespace rt
91+
92+
namespace rt_alt {
93+
extern const char *UnwindInfoManagerInstanceName;
94+
extern const char *UnwindInfoManagerFindSectionsHelperName;
95+
extern const char *UnwindInfoManagerEnableWrapperName;
96+
extern const char *UnwindInfoManagerDisableWrapperName;
97+
extern const char *UnwindInfoManagerRegisterActionName;
98+
extern const char *UnwindInfoManagerDeregisterActionName;
99+
} // end namespace rt_alt
91100
} // end namespace orc
92101
} // end namespace llvm
93102

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===--- UnwindInfoManager.h -- Register unwind info sections ---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Utilities for managing eh-frame and compact-unwind registration and lookup
10+
// through libunwind's find_dynamic_unwind_sections mechanism.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
15+
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
16+
17+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
18+
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
19+
#include "llvm/Support/Error.h"
20+
#include <map>
21+
#include <mutex>
22+
23+
namespace llvm::orc {
24+
25+
class UnwindInfoManager : public ExecutorBootstrapService {
26+
public:
27+
// This struct's layout should match the unw_dynamic_unwind_sections struct
28+
// from libunwind/src/libunwid_ext.h.
29+
struct UnwindSections {
30+
uintptr_t dso_base;
31+
uintptr_t dwarf_section;
32+
size_t dwarf_section_length;
33+
uintptr_t compact_unwind_section;
34+
size_t compact_unwind_section_length;
35+
};
36+
37+
/// If the libunwind find-dynamic-unwind-info callback registration APIs are
38+
/// available then this method will return an UnwindInfoManager instance,
39+
/// otherwise it will return nullptr.
40+
static std::unique_ptr<UnwindInfoManager> TryCreate();
41+
42+
Error shutdown() override;
43+
void addBootstrapSymbols(StringMap<ExecutorAddr> &M) override;
44+
45+
Error enable(void *FindDynamicUnwindSections);
46+
Error disable(void);
47+
48+
Error registerSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges,
49+
orc::ExecutorAddr DSOBase,
50+
orc::ExecutorAddrRange DWARFEHFrame,
51+
orc::ExecutorAddrRange CompactUnwind);
52+
53+
Error deregisterSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges);
54+
55+
int findSections(uintptr_t Addr, UnwindSections *Info);
56+
57+
private:
58+
UnwindInfoManager(int (*AddFindDynamicUnwindSections)(void *),
59+
int (*RemoveFindDynamicUnwindSections)(void *))
60+
: AddFindDynamicUnwindSections(AddFindDynamicUnwindSections),
61+
RemoveFindDynamicUnwindSections(RemoveFindDynamicUnwindSections) {}
62+
63+
static int findSectionsHelper(UnwindInfoManager *Instance, uintptr_t Addr,
64+
UnwindSections *Info);
65+
66+
std::mutex M;
67+
std::map<uintptr_t, UnwindSections> UWSecs;
68+
69+
int (*AddFindDynamicUnwindSections)(void *) = nullptr;
70+
int (*RemoveFindDynamicUnwindSections)(void *) = nullptr;
71+
void *FindDynamicUnwindSections = nullptr;
72+
73+
static const char *AddFnName, *RemoveFnName;
74+
};
75+
76+
} // namespace llvm::orc
77+
78+
#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===- UnwindInfoRegistrationPlugin.h -- libunwind registration -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Register eh-frame and compact-unwind sections with libunwind
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H
14+
#define LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H
15+
16+
#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h"
17+
18+
namespace llvm::orc {
19+
20+
class UnwindInfoRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
21+
public:
22+
static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
23+
Create(IRLayer &IRL, JITDylib &PlatformJD, ExecutorAddr Instance,
24+
ExecutorAddr FindHelper, ExecutorAddr Enable, ExecutorAddr Disable,
25+
ExecutorAddr Register, ExecutorAddr Deregister);
26+
27+
static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
28+
Create(IRLayer &IRL, JITDylib &PlatformJD);
29+
30+
~UnwindInfoRegistrationPlugin();
31+
32+
void modifyPassConfig(MaterializationResponsibility &MR,
33+
jitlink::LinkGraph &G,
34+
jitlink::PassConfiguration &PassConfig) override;
35+
36+
Error notifyEmitted(MaterializationResponsibility &MR) override {
37+
return Error::success();
38+
}
39+
40+
Error notifyFailed(MaterializationResponsibility &MR) override {
41+
return Error::success();
42+
}
43+
44+
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
45+
return Error::success();
46+
}
47+
48+
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
49+
ResourceKey SrcKey) override {}
50+
51+
private:
52+
UnwindInfoRegistrationPlugin(ExecutionSession &ES, ExecutorAddr Instance,
53+
ExecutorAddr Disable, ExecutorAddr Register,
54+
ExecutorAddr Deregister)
55+
: ES(ES), Instance(Instance), Disable(Disable), Register(Register),
56+
Deregister(Deregister) {
57+
DSOBaseName = ES.intern("__jitlink$libunwind_dso_base");
58+
}
59+
60+
static Expected<ThreadSafeModule> makeBouncerModule(ExecutionSession &ES);
61+
Error addUnwindInfoRegistrationActions(jitlink::LinkGraph &G);
62+
63+
ExecutionSession &ES;
64+
SymbolStringPtr DSOBaseName;
65+
ExecutorAddr Instance, Disable, Register, Deregister;
66+
};
67+
68+
} // namespace llvm::orc
69+
70+
#endif // LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H

llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs)
33
add_public_tablegen_target(JITLinkTableGen)
44

55
add_llvm_component_library(LLVMJITLink
6+
CompactUnwindSupport.cpp
67
DWARFRecordSectionSplitter.cpp
78
EHFrameSupport.cpp
89
JITLink.cpp
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//=------- CompactUnwindSupport.cpp - Compact Unwind format support -------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Compact Unwind support.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "CompactUnwindSupport.h"
14+
15+
#include "llvm/ADT/Sequence.h"
16+
17+
#define DEBUG_TYPE "jitlink"
18+
19+
namespace llvm {
20+
namespace jitlink {
21+
22+
Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection,
23+
size_t RecordSize) {
24+
25+
std::vector<Block *> OriginalBlocks(CompactUnwindSection.blocks().begin(),
26+
CompactUnwindSection.blocks().end());
27+
LLVM_DEBUG({
28+
dbgs() << "In " << G.getName() << " splitting compact unwind section "
29+
<< CompactUnwindSection.getName() << " containing "
30+
<< OriginalBlocks.size() << " initial blocks...\n";
31+
});
32+
33+
while (!OriginalBlocks.empty()) {
34+
auto *B = OriginalBlocks.back();
35+
OriginalBlocks.pop_back();
36+
37+
if (B->getSize() == 0) {
38+
LLVM_DEBUG({
39+
dbgs() << " Skipping empty block at "
40+
<< formatv("{0:x16}", B->getAddress()) << "\n";
41+
});
42+
continue;
43+
}
44+
45+
unsigned NumBlocks = B->getSize() / RecordSize;
46+
47+
LLVM_DEBUG({
48+
dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())
49+
<< " into " << NumBlocks << " compact unwind record(s)\n";
50+
});
51+
52+
if (B->getSize() % RecordSize)
53+
return make_error<JITLinkError>(
54+
"Error splitting compact unwind record in " + G.getName() +
55+
": block at " + formatv("{0:x}", B->getAddress()) + " has size " +
56+
formatv("{0:x}", B->getSize()) +
57+
" (not a multiple of CU record size of " +
58+
formatv("{0:x}", RecordSize) + ")");
59+
60+
auto Blocks =
61+
G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {
62+
return Idx * RecordSize;
63+
}));
64+
65+
for (auto *CURec : Blocks) {
66+
bool AddedKeepAlive = false;
67+
68+
for (auto &E : CURec->edges()) {
69+
if (E.getOffset() == 0) {
70+
LLVM_DEBUG({
71+
dbgs() << " Updating compact unwind record at "
72+
<< CURec->getAddress() << " to point to "
73+
<< (E.getTarget().hasName() ? *E.getTarget().getName()
74+
: StringRef())
75+
<< " (at " << E.getTarget().getAddress() << ")\n";
76+
});
77+
78+
if (E.getTarget().isExternal())
79+
return make_error<JITLinkError>(
80+
"Error adding keep-alive edge for compact unwind record at " +
81+
formatv("{0:x}", CURec->getAddress()) + ": target " +
82+
*E.getTarget().getName() + " is an external symbol");
83+
auto &TgtBlock = E.getTarget().getBlock();
84+
auto &CURecSym =
85+
G.addAnonymousSymbol(*CURec, 0, RecordSize, false, false);
86+
TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
87+
AddedKeepAlive = true;
88+
}
89+
}
90+
91+
if (!AddedKeepAlive)
92+
return make_error<JITLinkError>(
93+
"Error adding keep-alive edge for compact unwind record at " +
94+
formatv("{0:x}", CURec->getAddress()) +
95+
": no outgoing target edge at offset 0");
96+
}
97+
}
98+
99+
return Error::success();
100+
}
101+
102+
} // end namespace jitlink
103+
} // end namespace llvm

0 commit comments

Comments
 (0)