[llvm-branch-commits] [clang] [compiler-rt] [llvm] release/20.x: [ORC-RT] Use templates to express deeply nested function calls in testcase. (PR #126015)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Feb 5 22:47:55 PST 2025
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/126015
Backport 7fb233f549dee0346332562de050ef2ab3654329 a1ff2d18466bc27d3dc9b8bba688454e2a1cf196 b46211bbf683b30b88e41a684633fc63436e5edf c0f7ebe715dbe706224389a3022e6a3880fef0a1 b84ac58dce65ea94994c24f40a14208c47f8119f 52b5e3638a39e977bebb491312a6f7c53314efec 9de581b206eceac331aa26e13b62a9a35bfd406f eae6d6d18bd4d9e7dfe5fc1206d23d8ef663c8c7 aefa30e2301f155d4f4737d6f6c55c66eac58b2d 88f55d16c4c247a9eef326961a1445dee3f2e30c 4a2a8ed70da7ec44f0aa9092595e5b0f81a7e841 9d88ffe7f7b4a46d3bcb7bbdf0d7eb037ab5ba04 7a213e70eb24e621042f2fda043622048cb1f1df e00f824e9a5ea73830bd346115968fa9ace84cbf
Requested by: @lhames
>From 681592ea9316ab7d0e902152ab0cceb8492588ce Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 30 Jan 2025 16:03:00 +1100
Subject: [PATCH 01/14] [ORC] Fix file comment formatting. NFC.
(cherry picked from commit 7fb233f549dee0346332562de050ef2ab3654329)
---
llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index aae7369fc29c4c8..7f0a45941cf9bc7 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -1,5 +1,4 @@
-//===------ ELFNixPlatform.cpp - Utilities for executing ELFNix in Orc
-//-----===//
+//===----- ELFNixPlatform.cpp - Utilities for executing ELFNix in Orc -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
>From 33e3e06d8d560cfdb9bbda7cc572032a31ab8256 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Mon, 3 Feb 2025 18:34:39 +1100
Subject: [PATCH 02/14] [ORC] Drop 'Info' from
MachOCompactUnwindInfoSectionName.
Rename MachOCompactUnwindInfoSectionName to MachOCompactUnwindSectionName.
Background:
There are two related sections used for compact-unwind info processing:
__LD,__compact_unwind -- the input table stored in relocatable object formats,
and __TEXT,__unwind_info -- the compressed table produced by the linker and
consumed by libunwind. To keep the distinction clear we'll use *CompactUnwind*
for names that refer to the __LD,__compact_unwind input tables and *UnwindInfo*
for names that refer to the __TEXT,__unwind_info output tables. Dropping 'Info'
from the variable above clarifies which section it refers to.
(cherry picked from commit a1ff2d18466bc27d3dc9b8bba688454e2a1cf196)
---
.../llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h | 2 +-
llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp | 3 +--
llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
index b927dfbce992a0d..31d0ecca2080595 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
@@ -25,7 +25,7 @@ namespace orc {
extern StringRef MachODataCommonSectionName;
extern StringRef MachODataDataSectionName;
extern StringRef MachOEHFrameSectionName;
-extern StringRef MachOCompactUnwindInfoSectionName;
+extern StringRef MachOCompactUnwindSectionName;
extern StringRef MachOCStringSectionName;
extern StringRef MachOModInitFuncSectionName;
extern StringRef MachOObjCCatListSectionName;
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 48d54190fafb6ae..9479a69d4f0ba05 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1278,8 +1278,7 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
- if (Section *CUInfoSec =
- G.findSectionByName(MachOCompactUnwindInfoSectionName))
+ if (Section *CUInfoSec = G.findSectionByName(MachOCompactUnwindSectionName))
ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
// If we didn't find any pointed-to code-blocks then there's no need to
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
index 11e8eb7bc3a19b1..be92acd37aa8de3 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
@@ -18,7 +18,7 @@ namespace orc {
StringRef MachODataCommonSectionName = "__DATA,__common";
StringRef MachODataDataSectionName = "__DATA,__data";
StringRef MachOEHFrameSectionName = "__TEXT,__eh_frame";
-StringRef MachOCompactUnwindInfoSectionName = "__TEXT,__unwind_info";
+StringRef MachOCompactUnwindSectionName = "__TEXT,__unwind_info";
StringRef MachOCStringSectionName = "__TEXT,__cstring";
StringRef MachOModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef MachOObjCCatListSectionName = "__DATA,__objc_catlist";
>From d6d08a82a745c46582339c785c7e4817e0cea3c5 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 4 Feb 2025 16:17:53 +1100
Subject: [PATCH 03/14] [ORC] Add minimal-throw-catch.ll regression test for
lli -jit-mode=orc.
We already had a -jit-mode=orc-lazy regression test for this, but it should
work equally well in non-lazy mode.
(cherry picked from commit b46211bbf683b30b88e41a684633fc63436e5edf)
---
.../Orc/minimal-throw-catch.ll | 52 +++++++++++++++++++
.../OrcLazy/minimal-throw-catch.ll | 4 --
2 files changed, 52 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
diff --git a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
new file mode 100644
index 000000000000000..cd22ec65ed9996e
--- /dev/null
+++ b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
@@ -0,0 +1,52 @@
+; REQUIRES: x86_64-apple
+; RUN: lli -jit-kind=orc-lazy %s
+;
+; Basic correctness testing for eh-frame processing and registration.
+
+ at _ZTIi = external constant ptr
+
+declare ptr @__cxa_allocate_exception(i64)
+declare void @__cxa_throw(ptr, ptr, ptr)
+
+declare i32 @__gxx_personality_v0(...)
+declare i32 @llvm.eh.typeid.for(ptr)
+declare ptr @__cxa_begin_catch(ptr)
+declare void @__cxa_end_catch()
+
+define void @explode() {
+entry:
+ %exception = tail call ptr @__cxa_allocate_exception(i64 4)
+ store i32 42, ptr %exception, align 16
+ tail call void @__cxa_throw(ptr %exception, ptr @_ZTIi, ptr null)
+ unreachable
+}
+
+define i32 @main(i32 %argc, ptr %argv) personality ptr @__gxx_personality_v0 {
+entry:
+ invoke void @explode()
+ to label %return unwind label %lpad
+
+lpad:
+ %0 = landingpad { ptr, i32 }
+ catch ptr @_ZTIi
+ %1 = extractvalue { ptr, i32 } %0, 1
+ %2 = tail call i32 @llvm.eh.typeid.for(ptr @_ZTIi)
+ %matches = icmp eq i32 %1, %2
+ br i1 %matches, label %catch, label %eh.resume
+
+catch:
+ %3 = extractvalue { ptr, i32 } %0, 0
+ %4 = tail call ptr @__cxa_begin_catch(ptr %3)
+ %5 = load i32, ptr %4, align 4
+ %cmp = icmp ne i32 %5, 42
+ %cond = zext i1 %cmp to i32
+ tail call void @__cxa_end_catch()
+ br label %return
+
+return:
+ %retval.0 = phi i32 [ %cond, %catch ], [ 2, %entry ]
+ ret i32 %retval.0
+
+eh.resume:
+ resume { ptr, i32 } %0
+}
diff --git a/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
index 5bc5769a2c0d2f8..cd22ec65ed9996e 100644
--- a/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
+++ b/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
@@ -3,10 +3,6 @@
;
; Basic correctness testing for eh-frame processing and registration.
-source_filename = "minimal-throw-catch.cpp"
-target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-apple-macosx10.14.0"
-
@_ZTIi = external constant ptr
declare ptr @__cxa_allocate_exception(i64)
>From b34b4c22a879377e1b00157bf2f33fb62335f4f1 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 4 Feb 2025 17:38:16 +1100
Subject: [PATCH 04/14] [ORC] Actually use -jit-kind=orc for the new
minimal-throw-catch.ll test.
b46211bbf68, which introduced a new copy of the minimal-throw-catch.ll test,
failed to update the run line.
(cherry picked from commit c0f7ebe715dbe706224389a3022e6a3880fef0a1)
---
llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
index cd22ec65ed9996e..1b8f45184833ffe 100644
--- a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
+++ b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
@@ -1,5 +1,5 @@
; REQUIRES: x86_64-apple
-; RUN: lli -jit-kind=orc-lazy %s
+; RUN: lli -jit-kind=orc %s
;
; Basic correctness testing for eh-frame processing and registration.
>From a63aaa5c92e5028829cfdc95acb1b839bd86e85d Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 4 Feb 2025 18:09:07 +1100
Subject: [PATCH 05/14] [ORC] Rename MachOCompactUnwindSectionName to
MachOUnwindInfoSectionName.
a1ff2d18466 should have disambiguated MachOCompactUnwindInfoSectionName to
MachOUnwindInfoSectionName, given how it's used in MachOPlatform and its
value.
A MachOCompactUnwindSectionName variable with an appropriate value will be
added in an upcoming patch to re-enable compact-unwind support in JITLink.
(cherry picked from commit b84ac58dce65ea94994c24f40a14208c47f8119f)
---
.../include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h | 2 +-
llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp | 2 +-
llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
index 31d0ecca2080595..5de85a4f8674e1d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
@@ -25,7 +25,6 @@ namespace orc {
extern StringRef MachODataCommonSectionName;
extern StringRef MachODataDataSectionName;
extern StringRef MachOEHFrameSectionName;
-extern StringRef MachOCompactUnwindSectionName;
extern StringRef MachOCStringSectionName;
extern StringRef MachOModInitFuncSectionName;
extern StringRef MachOObjCCatListSectionName;
@@ -53,6 +52,7 @@ extern StringRef MachOTextTextSectionName;
extern StringRef MachOThreadBSSSectionName;
extern StringRef MachOThreadDataSectionName;
extern StringRef MachOThreadVarsSectionName;
+extern StringRef MachOUnwindInfoSectionName;
extern StringRef MachOInitSectionNames[22];
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 9479a69d4f0ba05..43d38c81fb8a67c 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1278,7 +1278,7 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
- if (Section *CUInfoSec = G.findSectionByName(MachOCompactUnwindSectionName))
+ if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName))
ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
// If we didn't find any pointed-to code-blocks then there's no need to
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
index be92acd37aa8de3..d94acf276881771 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
@@ -18,7 +18,6 @@ namespace orc {
StringRef MachODataCommonSectionName = "__DATA,__common";
StringRef MachODataDataSectionName = "__DATA,__data";
StringRef MachOEHFrameSectionName = "__TEXT,__eh_frame";
-StringRef MachOCompactUnwindSectionName = "__TEXT,__unwind_info";
StringRef MachOCStringSectionName = "__TEXT,__cstring";
StringRef MachOModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef MachOObjCCatListSectionName = "__DATA,__objc_catlist";
@@ -46,6 +45,7 @@ StringRef MachOTextTextSectionName = "__TEXT,__text";
StringRef MachOThreadBSSSectionName = "__DATA,__thread_bss";
StringRef MachOThreadDataSectionName = "__DATA,__thread_data";
StringRef MachOThreadVarsSectionName = "__DATA,__thread_vars";
+StringRef MachOUnwindInfoSectionName = "__TEXT,__unwind_info";
StringRef MachOInitSectionNames[22] = {
MachOModInitFuncSectionName, MachOObjCCatListSectionName,
>From 809926b94b8f3396f3b77ad18eebf0529d987964 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 4 Feb 2025 22:34:38 +1100
Subject: [PATCH 06/14] [ORC] Fix eh-frame record target finding in
MachOPlatform.
Unwind-info records only have one keep-alive edge to their target function, but
eh-frame records may have multiple edges (to the CIE, function, personality, and
lsda). We need to identify the target-function edge differently for each section
type.
(cherry picked from commit 52b5e3638a39e977bebb491312a6f7c53314efec)
---
.../lib/ExecutionEngine/Orc/MachOPlatform.cpp | 57 ++++++++++++++-----
1 file changed, 44 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 43d38c81fb8a67c..cea0e984718f2a0 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1256,7 +1256,8 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
// ScanSection records a section range and adds any executable blocks that
// that section points to to the CodeBlocks vector.
SmallVector<Block *> CodeBlocks;
- auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
+ auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange,
+ auto GetCodeForRecord) {
if (Sec.blocks().empty())
return;
SecRange = (*Sec.blocks().begin())->getRange();
@@ -1264,22 +1265,52 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
auto R = B->getRange();
SecRange.Start = std::min(SecRange.Start, R.Start);
SecRange.End = std::max(SecRange.End, R.End);
- for (auto &E : B->edges()) {
- if (E.getKind() != Edge::KeepAlive || !E.getTarget().isDefined())
- continue;
- auto &TargetBlock = E.getTarget().getBlock();
- auto &TargetSection = TargetBlock.getSection();
- if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
- CodeBlocks.push_back(&TargetBlock);
- }
+ if (auto *CodeBlock = GetCodeForRecord(*B))
+ CodeBlocks.push_back(CodeBlock);
}
};
- if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName))
- ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection);
+ if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) {
+ ScanUnwindInfoSection(
+ *EHFrameSec, US.DwarfSection, [&](Block &B) -> Block * {
+ // Filter out CIE, personality, etc. edges.
+ SmallVector<Edge *, 4> BEdges;
+ for (auto &E : B.edges())
+ BEdges.push_back(&E);
+ llvm::sort(BEdges, [](const Edge *LHS, const Edge *RHS) {
+ return LHS->getOffset() < RHS->getOffset();
+ });
+ if (BEdges.size() < 2)
+ return nullptr;
+ auto &TargetBlock = BEdges[1]->getTarget().getBlock();
+#ifndef NDEBUG
+ auto &TargetSection = TargetBlock.getSection();
+ assert(&TargetSection != EHFrameSec &&
+ (TargetSection.getMemProt() & MemProt::Exec) ==
+ MemProt::Exec &&
+ "Invalid eh-frame function target");
+#endif // NDEBUG
+ return &TargetBlock;
+ });
+ }
- if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName))
- ScanUnwindInfoSection(*CUInfoSec, US.CompactUnwindSection);
+ if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName)) {
+ ScanUnwindInfoSection(
+ *CUInfoSec, US.CompactUnwindSection, [&](Block &B) -> Block * {
+ // Compact unwind records should just have a keep-alive pointing to
+ // the target function.
+ assert(B.edges_size() == 1 &&
+ "unwind-info record should only have one edge");
+ for (auto &E : B.edges()) {
+ assert(E.getTarget().isDefined() &&
+ "unwind-info record edge has external target");
+ assert(E.getKind() == Edge::KeepAlive &&
+ "unwind-info record has unexpected edge kind");
+ return &E.getTarget().getBlock();
+ }
+ return nullptr;
+ });
+ }
// If we didn't find any pointed-to code-blocks then there's no need to
// register any info.
>From 9634139052880608fe0e4f59568cd0bb62a87f5e Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Wed, 5 Feb 2025 13:25:50 +1100
Subject: [PATCH 07/14] [ORC] Moch MachOPlatform unwind-info fixes.
Some eh-frame records are CIEs, which don't point to functions. We need to skip
these records. This patch reuses EHFrameCFIBlockInspector to identify function
targets, rather than a custom loop. Any performance impact will be minimal, and
essentially irrelevant once compact-unwind support re-lands (since at that
point we'll discard most eh-frame records).
For unwind-info sections: don't assume one block per record: the unwind-info
section packs all records into a single block.
(cherry picked from commit 9de581b206eceac331aa26e13b62a9a35bfd406f)
---
.../lib/ExecutionEngine/Orc/MachOPlatform.cpp | 42 +++++--------------
1 file changed, 11 insertions(+), 31 deletions(-)
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index cea0e984718f2a0..44ae73671f5b15a 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -9,6 +9,7 @@
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/JITLink/MachO.h"
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
@@ -1257,7 +1258,7 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
// that section points to to the CodeBlocks vector.
SmallVector<Block *> CodeBlocks;
auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange,
- auto GetCodeForRecord) {
+ auto AddCodeBlocks) {
if (Sec.blocks().empty())
return;
SecRange = (*Sec.blocks().begin())->getRange();
@@ -1265,50 +1266,29 @@ MachOPlatform::MachOPlatformPlugin::findUnwindSectionInfo(
auto R = B->getRange();
SecRange.Start = std::min(SecRange.Start, R.Start);
SecRange.End = std::max(SecRange.End, R.End);
- if (auto *CodeBlock = GetCodeForRecord(*B))
- CodeBlocks.push_back(CodeBlock);
+ AddCodeBlocks(*B);
}
};
if (Section *EHFrameSec = G.findSectionByName(MachOEHFrameSectionName)) {
- ScanUnwindInfoSection(
- *EHFrameSec, US.DwarfSection, [&](Block &B) -> Block * {
- // Filter out CIE, personality, etc. edges.
- SmallVector<Edge *, 4> BEdges;
- for (auto &E : B.edges())
- BEdges.push_back(&E);
- llvm::sort(BEdges, [](const Edge *LHS, const Edge *RHS) {
- return LHS->getOffset() < RHS->getOffset();
- });
- if (BEdges.size() < 2)
- return nullptr;
- auto &TargetBlock = BEdges[1]->getTarget().getBlock();
-#ifndef NDEBUG
- auto &TargetSection = TargetBlock.getSection();
- assert(&TargetSection != EHFrameSec &&
- (TargetSection.getMemProt() & MemProt::Exec) ==
- MemProt::Exec &&
- "Invalid eh-frame function target");
-#endif // NDEBUG
- return &TargetBlock;
- });
+ ScanUnwindInfoSection(*EHFrameSec, US.DwarfSection, [&](Block &B) {
+ if (auto *Fn = jitlink::EHFrameCFIBlockInspector::FromEdgeScan(B)
+ .getPCBeginEdge())
+ if (Fn->getTarget().isDefined())
+ CodeBlocks.push_back(&Fn->getTarget().getBlock());
+ });
}
if (Section *CUInfoSec = G.findSectionByName(MachOUnwindInfoSectionName)) {
ScanUnwindInfoSection(
- *CUInfoSec, US.CompactUnwindSection, [&](Block &B) -> Block * {
- // Compact unwind records should just have a keep-alive pointing to
- // the target function.
- assert(B.edges_size() == 1 &&
- "unwind-info record should only have one edge");
+ *CUInfoSec, US.CompactUnwindSection, [&](Block &B) {
for (auto &E : B.edges()) {
assert(E.getTarget().isDefined() &&
"unwind-info record edge has external target");
assert(E.getKind() == Edge::KeepAlive &&
"unwind-info record has unexpected edge kind");
- return &E.getTarget().getBlock();
+ CodeBlocks.push_back(&E.getTarget().getBlock());
}
- return nullptr;
});
}
>From 042e997b1a1680c646f6b2ca7100a897f11afc98 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Tue, 4 Feb 2025 13:21:33 +1100
Subject: [PATCH 08/14] Re-reapply "[ORC] Enable JIT support for the
compact-unwind..." with fixes.
Re-enables compact-unwind support in JITLink, which was reverted in b04847b427d
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.
(cherry picked from commit eae6d6d18bd4d9e7dfe5fc1206d23d8ef663c8c7)
---
clang/test/Interpreter/simple-exception.cpp | 4 +-
compiler-rt/lib/orc/macho_platform.cpp | 6 +
.../TestCases/Darwin/Generic/exceptions.cpp | 13 +
llvm/include/llvm/ExecutionEngine/Orc/Core.h | 9 +-
.../Orc/ExecutorProcessControl.h | 4 +
.../Orc/Shared/MachOObjectFormat.h | 1 +
.../ExecutionEngine/Orc/Shared/OrcRTBridge.h | 9 +
.../Orc/TargetProcess/UnwindInfoManager.h | 78 +++
.../Orc/UnwindInfoRegistrationPlugin.h | 70 ++
.../ExecutionEngine/JITLink/CMakeLists.txt | 1 +
.../JITLink/CompactUnwindSupport.cpp | 103 +++
.../JITLink/CompactUnwindSupport.h | 653 ++++++++++++++++++
.../JITLink/MachOLinkGraphBuilder.cpp | 116 ----
.../JITLink/MachOLinkGraphBuilder.h | 11 -
.../ExecutionEngine/JITLink/MachO_arm64.cpp | 54 +-
.../ExecutionEngine/JITLink/MachO_x86_64.cpp | 63 +-
llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 +
llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp | 3 +
llvm/lib/ExecutionEngine/Orc/Core.cpp | 34 +-
.../Orc/EHFrameRegistrationPlugin.cpp | 13 +-
.../Orc/ExecutorProcessControl.cpp | 7 +
llvm/lib/ExecutionEngine/Orc/LLJIT.cpp | 31 +-
.../Orc/Shared/MachOObjectFormat.cpp | 1 +
.../Orc/Shared/OrcRTBridge.cpp | 14 +
.../Orc/TargetProcess/CMakeLists.txt | 1 +
.../Orc/TargetProcess/UnwindInfoManager.cpp | 188 +++++
.../Orc/UnwindInfoRegistrationPlugin.cpp | 238 +++++++
.../Orc/minimal-throw-catch.ll | 2 +-
.../OrcLazy/minimal-throw-catch.ll | 2 +-
llvm/test/lit.cfg.py | 48 ++
30 files changed, 1606 insertions(+), 172 deletions(-)
create mode 100644 compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h
create mode 100644 llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h
create mode 100644 llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp
create mode 100644 llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
create mode 100644 llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp
create mode 100644 llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp
diff --git a/clang/test/Interpreter/simple-exception.cpp b/clang/test/Interpreter/simple-exception.cpp
index 6749acd6e6bd23b..651e8d9402f89ee 100644
--- a/clang/test/Interpreter/simple-exception.cpp
+++ b/clang/test/Interpreter/simple-exception.cpp
@@ -1,7 +1,7 @@
// clang-format off
// UNSUPPORTED: system-aix
-// XFAIL for arm and arm64, or running on Windows.
-// XFAIL: target=arm{{.*}}, system-windows
+// XFAIL for arm, or running on Windows.
+// XFAIL: target=arm-{{.*}}, target=armv{{.*}}, system-windows
// RUN: cat %s | clang-repl | FileCheck %s
// Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter
diff --git a/compiler-rt/lib/orc/macho_platform.cpp b/compiler-rt/lib/orc/macho_platform.cpp
index 8ca68587aeb363f..4b603fd95e3163d 100644
--- a/compiler-rt/lib/orc/macho_platform.cpp
+++ b/compiler-rt/lib/orc/macho_platform.cpp
@@ -557,6 +557,12 @@ Error MachOPlatformRuntimeState::registerObjectPlatformSections(
return make_error<StringError>(ErrStream.str());
}
+ ORC_RT_DEBUG({
+ printdbg(" UnwindInfo: %s, UseCallbackStyleUnwindInfo: %s\n",
+ UnwindInfo ? "true" : "false",
+ UseCallbackStyleUnwindInfo ? "true" : "false");
+ });
+
if (UnwindInfo && UseCallbackStyleUnwindInfo) {
ORC_RT_DEBUG({
printdbg(" Registering new-style unwind info for:\n"
diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
new file mode 100644
index 000000000000000..7e9c40c724aec6c
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
@@ -0,0 +1,13 @@
+// RUN: %clangxx -c -o %t %s
+// RUN: %llvm_jitlink -slab-allocate=20Mb %t
+//
+// REQUIRES: system-darwin && host-arch-compatible
+
+int main(int argc, char *argv[]) {
+ try {
+ throw 42;
+ } catch (int E) {
+ return 42 - E;
+ }
+ return 1;
+}
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Core.h b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
index db853362f65733a..3eddaf4c9c59ff4 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Core.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Core.h
@@ -1204,8 +1204,13 @@ class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
JITDylib(ExecutionSession &ES, std::string Name);
- std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
- IL_removeTracker(ResourceTracker &RT);
+ struct RemoveTrackerResult {
+ AsynchronousSymbolQuerySet QueriesToFail;
+ std::shared_ptr<SymbolDependenceMap> FailedSymbols;
+ std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;
+ };
+
+ RemoveTrackerResult IL_removeTracker(ResourceTracker &RT);
void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
index dcf5592f1717c2d..86e98e74b7055bc 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
@@ -20,6 +20,7 @@
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h"
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
@@ -507,6 +508,9 @@ class SelfExecutorProcessControl : public ExecutorProcessControl,
SymbolLookupCompleteFn F) override;
std::unique_ptr<jitlink::JITLinkMemoryManager> OwnedMemMgr;
+#ifdef __APPLE__
+ std::unique_ptr<UnwindInfoManager> UnwindInfoMgr;
+#endif // __APPLE__
char GlobalManglingPrefix = 0;
};
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
index 5de85a4f8674e1d..8eb8c1b4cc89dd6 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h
@@ -25,6 +25,7 @@ namespace orc {
extern StringRef MachODataCommonSectionName;
extern StringRef MachODataDataSectionName;
extern StringRef MachOEHFrameSectionName;
+extern StringRef MachOCompactUnwindSectionName;
extern StringRef MachOCStringSectionName;
extern StringRef MachOModInitFuncSectionName;
extern StringRef MachOObjCCatListSectionName;
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
index aed43f6308cbaa0..db5ff135a7164cf 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
@@ -88,6 +88,15 @@ using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddr,
using SPSRunAsVoidFunctionSignature = int32_t(shared::SPSExecutorAddr);
using SPSRunAsIntFunctionSignature = int32_t(shared::SPSExecutorAddr, int32_t);
} // end namespace rt
+
+namespace rt_alt {
+extern const char *UnwindInfoManagerInstanceName;
+extern const char *UnwindInfoManagerFindSectionsHelperName;
+extern const char *UnwindInfoManagerEnableWrapperName;
+extern const char *UnwindInfoManagerDisableWrapperName;
+extern const char *UnwindInfoManagerRegisterActionName;
+extern const char *UnwindInfoManagerDeregisterActionName;
+} // end namespace rt_alt
} // end namespace orc
} // end namespace llvm
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h
new file mode 100644
index 000000000000000..fc7719f28212223
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h
@@ -0,0 +1,78 @@
+//===--- UnwindInfoManager.h -- Register unwind info sections ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for managing eh-frame and compact-unwind registration and lookup
+// through libunwind's find_dynamic_unwind_sections mechanism.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
+#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
+
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
+#include "llvm/Support/Error.h"
+#include <map>
+#include <mutex>
+
+namespace llvm::orc {
+
+class UnwindInfoManager : public ExecutorBootstrapService {
+public:
+ // This struct's layout should match the unw_dynamic_unwind_sections struct
+ // from libunwind/src/libunwid_ext.h.
+ struct UnwindSections {
+ uintptr_t dso_base;
+ uintptr_t dwarf_section;
+ size_t dwarf_section_length;
+ uintptr_t compact_unwind_section;
+ size_t compact_unwind_section_length;
+ };
+
+ /// If the libunwind find-dynamic-unwind-info callback registration APIs are
+ /// available then this method will return an UnwindInfoManager instance,
+ /// otherwise it will return nullptr.
+ static std::unique_ptr<UnwindInfoManager> TryCreate();
+
+ Error shutdown() override;
+ void addBootstrapSymbols(StringMap<ExecutorAddr> &M) override;
+
+ Error enable(void *FindDynamicUnwindSections);
+ Error disable(void);
+
+ Error registerSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges,
+ orc::ExecutorAddr DSOBase,
+ orc::ExecutorAddrRange DWARFEHFrame,
+ orc::ExecutorAddrRange CompactUnwind);
+
+ Error deregisterSections(ArrayRef<orc::ExecutorAddrRange> CodeRanges);
+
+ int findSections(uintptr_t Addr, UnwindSections *Info);
+
+private:
+ UnwindInfoManager(int (*AddFindDynamicUnwindSections)(void *),
+ int (*RemoveFindDynamicUnwindSections)(void *))
+ : AddFindDynamicUnwindSections(AddFindDynamicUnwindSections),
+ RemoveFindDynamicUnwindSections(RemoveFindDynamicUnwindSections) {}
+
+ static int findSectionsHelper(UnwindInfoManager *Instance, uintptr_t Addr,
+ UnwindSections *Info);
+
+ std::mutex M;
+ std::map<uintptr_t, UnwindSections> UWSecs;
+
+ int (*AddFindDynamicUnwindSections)(void *) = nullptr;
+ int (*RemoveFindDynamicUnwindSections)(void *) = nullptr;
+ void *FindDynamicUnwindSections = nullptr;
+
+ static const char *AddFnName, *RemoveFnName;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_UNWINDINFOMANAGER_H
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h b/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h
new file mode 100644
index 000000000000000..eb883a79a93d87b
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h
@@ -0,0 +1,70 @@
+//===- UnwindInfoRegistrationPlugin.h -- libunwind registration -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Register eh-frame and compact-unwind sections with libunwind
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H
+#define LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H
+
+#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h"
+
+namespace llvm::orc {
+
+class UnwindInfoRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
+public:
+ static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
+ Create(IRLayer &IRL, JITDylib &PlatformJD, ExecutorAddr Instance,
+ ExecutorAddr FindHelper, ExecutorAddr Enable, ExecutorAddr Disable,
+ ExecutorAddr Register, ExecutorAddr Deregister);
+
+ static Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
+ Create(IRLayer &IRL, JITDylib &PlatformJD);
+
+ ~UnwindInfoRegistrationPlugin();
+
+ void modifyPassConfig(MaterializationResponsibility &MR,
+ jitlink::LinkGraph &G,
+ jitlink::PassConfiguration &PassConfig) override;
+
+ Error notifyEmitted(MaterializationResponsibility &MR) override {
+ return Error::success();
+ }
+
+ Error notifyFailed(MaterializationResponsibility &MR) override {
+ return Error::success();
+ }
+
+ Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
+ return Error::success();
+ }
+
+ void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+ ResourceKey SrcKey) override {}
+
+private:
+ UnwindInfoRegistrationPlugin(ExecutionSession &ES, ExecutorAddr Instance,
+ ExecutorAddr Disable, ExecutorAddr Register,
+ ExecutorAddr Deregister)
+ : ES(ES), Instance(Instance), Disable(Disable), Register(Register),
+ Deregister(Deregister) {
+ DSOBaseName = ES.intern("__jitlink$libunwind_dso_base");
+ }
+
+ static Expected<ThreadSafeModule> makeBouncerModule(ExecutionSession &ES);
+ Error addUnwindInfoRegistrationActions(jitlink::LinkGraph &G);
+
+ ExecutionSession &ES;
+ SymbolStringPtr DSOBaseName;
+ ExecutorAddr Instance, Disable, Register, Deregister;
+};
+
+} // namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_UNWINDINFOREGISTRATIONPLUGIN_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index e5f5a99c39bc004..65dd0c7468ae1df 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -3,6 +3,7 @@ tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(JITLinkTableGen)
add_llvm_component_library(LLVMJITLink
+ CompactUnwindSupport.cpp
DWARFRecordSectionSplitter.cpp
EHFrameSupport.cpp
JITLink.cpp
diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp
new file mode 100644
index 000000000000000..51e3d26479ffdf5
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.cpp
@@ -0,0 +1,103 @@
+//=------- CompactUnwindSupport.cpp - Compact Unwind format support -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Compact Unwind support.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompactUnwindSupport.h"
+
+#include "llvm/ADT/Sequence.h"
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection,
+ size_t RecordSize) {
+
+ std::vector<Block *> OriginalBlocks(CompactUnwindSection.blocks().begin(),
+ CompactUnwindSection.blocks().end());
+ LLVM_DEBUG({
+ dbgs() << "In " << G.getName() << " splitting compact unwind section "
+ << CompactUnwindSection.getName() << " containing "
+ << OriginalBlocks.size() << " initial blocks...\n";
+ });
+
+ while (!OriginalBlocks.empty()) {
+ auto *B = OriginalBlocks.back();
+ OriginalBlocks.pop_back();
+
+ if (B->getSize() == 0) {
+ LLVM_DEBUG({
+ dbgs() << " Skipping empty block at "
+ << formatv("{0:x16}", B->getAddress()) << "\n";
+ });
+ continue;
+ }
+
+ unsigned NumBlocks = B->getSize() / RecordSize;
+
+ LLVM_DEBUG({
+ dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())
+ << " into " << NumBlocks << " compact unwind record(s)\n";
+ });
+
+ if (B->getSize() % RecordSize)
+ return make_error<JITLinkError>(
+ "Error splitting compact unwind record in " + G.getName() +
+ ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +
+ formatv("{0:x}", B->getSize()) +
+ " (not a multiple of CU record size of " +
+ formatv("{0:x}", RecordSize) + ")");
+
+ auto Blocks =
+ G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {
+ return Idx * RecordSize;
+ }));
+
+ for (auto *CURec : Blocks) {
+ bool AddedKeepAlive = false;
+
+ for (auto &E : CURec->edges()) {
+ if (E.getOffset() == 0) {
+ LLVM_DEBUG({
+ dbgs() << " Updating compact unwind record at "
+ << CURec->getAddress() << " to point to "
+ << (E.getTarget().hasName() ? *E.getTarget().getName()
+ : StringRef())
+ << " (at " << E.getTarget().getAddress() << ")\n";
+ });
+
+ if (E.getTarget().isExternal())
+ return make_error<JITLinkError>(
+ "Error adding keep-alive edge for compact unwind record at " +
+ formatv("{0:x}", CURec->getAddress()) + ": target " +
+ *E.getTarget().getName() + " is an external symbol");
+ auto &TgtBlock = E.getTarget().getBlock();
+ auto &CURecSym =
+ G.addAnonymousSymbol(*CURec, 0, RecordSize, false, false);
+ TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
+ AddedKeepAlive = true;
+ }
+ }
+
+ if (!AddedKeepAlive)
+ return make_error<JITLinkError>(
+ "Error adding keep-alive edge for compact unwind record at " +
+ formatv("{0:x}", CURec->getAddress()) +
+ ": no outgoing target edge at offset 0");
+ }
+ }
+
+ return Error::success();
+}
+
+} // end namespace jitlink
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
new file mode 100644
index 000000000000000..dc3ed942aa8ac8a
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
@@ -0,0 +1,653 @@
+//===- CompactUnwindSupportImpl.h - Compact Unwind format impl --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Compact Unwind format support implementation details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H
+#define LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/JITLink/MachO.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+
+#define DEBUG_TYPE "jitlink_cu"
+
+namespace llvm {
+namespace jitlink {
+
+/// Split blocks in an __LD,__compact_unwind section on record boundaries.
+/// When this function returns edges within each record are guaranteed to be
+/// sorted by offset.
+Error splitCompactUnwindBlocks(LinkGraph &G, Section &CompactUnwindSection,
+ size_t RecordSize);
+
+/// CRTP base for compact unwind traits classes. Automatically provides derived
+/// constants.
+///
+/// FIXME: Passing PtrSize as a template parameter is a hack to work around a
+/// bug in older MSVC compilers (until at least MSVC 15) where constexpr
+/// fields in the CRTP impl class were not visible to the base class.
+/// Once we no longer need to support these compilers the PtrSize
+/// template argument should be removed and PointerSize should be
+/// defined as a member in the CRTP Impl classes.
+template <typename CRTPImpl, size_t PtrSize> struct CompactUnwindTraits {
+ static constexpr size_t PointerSize = PtrSize;
+ static constexpr size_t Size = 3 * PointerSize + 2 * 4;
+ static constexpr size_t FnFieldOffset = 0;
+ static constexpr size_t SizeFieldOffset = FnFieldOffset + PointerSize;
+ static constexpr size_t EncodingFieldOffset = SizeFieldOffset + 4;
+ static constexpr size_t PersonalityFieldOffset = EncodingFieldOffset + 4;
+ static constexpr size_t LSDAFieldOffset =
+ PersonalityFieldOffset + PointerSize;
+
+ static uint32_t readPCRangeSize(ArrayRef<char> RecordContent) {
+ assert(SizeFieldOffset + 4 <= RecordContent.size() &&
+ "Truncated CU record?");
+ return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() +
+ SizeFieldOffset);
+ }
+
+ static uint32_t readEncoding(ArrayRef<char> RecordContent) {
+ assert(EncodingFieldOffset + 4 <= RecordContent.size() &&
+ "Truncated CU record?");
+ return support::endian::read32<CRTPImpl::Endianness>(RecordContent.data() +
+ EncodingFieldOffset);
+ }
+};
+
+/// Architecture specific implementation of CompactUnwindManager.
+template <typename CURecTraits> class CompactUnwindManager {
+public:
+ CompactUnwindManager(StringRef CompactUnwindSectionName,
+ StringRef UnwindInfoSectionName,
+ StringRef EHFrameSectionName)
+ : CompactUnwindSectionName(CompactUnwindSectionName),
+ UnwindInfoSectionName(UnwindInfoSectionName),
+ EHFrameSectionName(EHFrameSectionName) {}
+
+ // Split compact unwind records, add keep-alive edges from functions to
+ // compact unwind records, and from compact unwind records to FDEs where
+ // needed.
+ //
+ // This method must be called *after* __eh_frame has been processed: it
+ // assumes that eh-frame records have been split up and keep-alive edges have
+ // been inserted.
+ Error prepareForPrune(LinkGraph &G) {
+ Section *CUSec = G.findSectionByName(CompactUnwindSectionName);
+ if (!CUSec || CUSec->empty()) {
+ LLVM_DEBUG({
+ dbgs() << "Compact unwind: No compact unwind info for " << G.getName()
+ << "\n";
+ });
+ return Error::success();
+ }
+
+ LLVM_DEBUG({
+ dbgs() << "Compact unwind: preparing " << G.getName() << " for prune\n";
+ });
+
+ Section *EHFrameSec = G.findSectionByName(EHFrameSectionName);
+
+ if (auto Err = splitCompactUnwindBlocks(G, *CUSec, CURecTraits::Size))
+ return Err;
+
+ LLVM_DEBUG({
+ dbgs() << " Preparing " << CUSec->blocks_size() << " blocks in "
+ << CompactUnwindSectionName << "\n";
+ });
+
+ for (auto *B : CUSec->blocks()) {
+
+ // Find target function edge.
+ Edge *PCBeginEdge = nullptr;
+ for (auto &E : B->edges_at(CURecTraits::FnFieldOffset)) {
+ PCBeginEdge = &E;
+ break;
+ }
+
+ if (!PCBeginEdge)
+ return make_error<JITLinkError>(
+ "In " + G.getName() + ", compact unwind record at " +
+ formatv("{0:x}", B->getAddress()) + " has no pc-begin edge");
+
+ if (!PCBeginEdge->getTarget().isDefined())
+ return make_error<JITLinkError>(
+ "In " + G.getName() + ", compact unwind record at " +
+ formatv("{0:x}", B->getAddress()) + " points at external symbol " +
+ *PCBeginEdge->getTarget().getName());
+
+ auto &Fn = PCBeginEdge->getTarget();
+
+ if (!Fn.isDefined()) {
+ LLVM_DEBUG({
+ dbgs() << "In " << CompactUnwindSectionName << " for " << G.getName()
+ << " encountered unexpected pc-edge to undefined symbol "
+ << 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()));
+
+ auto &CURecSym =
+ G.addAnonymousSymbol(*B, 0, CURecTraits::Size, false, false);
+
+ bool KeepAliveAlreadyPresent = false;
+ if (EHFrameSec) {
+ Edge *KeepAliveEdge = nullptr;
+ for (auto &E : Fn.getBlock().edges_at(0)) {
+ if (E.getKind() == Edge::KeepAlive && E.getTarget().isDefined() &&
+ &E.getTarget().getBlock().getSection() == EHFrameSec) {
+ KeepAliveEdge = &E;
+ break;
+ }
+ }
+
+ if (KeepAliveEdge) {
+ // Found a keep-alive edge to an FDE in the eh-frame. Switch the keep
+ // alive edge to point to the CU and if the CU needs DWARF then add
+ // an extra keep-alive edge from the CU to the FDE.
+ auto &FDE = KeepAliveEdge->getTarget();
+ KeepAliveEdge->setTarget(CURecSym);
+ KeepAliveAlreadyPresent = true;
+ if (NeedsDWARF) {
+ LLVM_DEBUG({
+ dbgs() << " Needs DWARF: adding keep-alive edge to FDE at "
+ << FDE.getAddress() << "\n";
+ });
+ B->addEdge(Edge::KeepAlive, 0, FDE, 0);
+ }
+ } else {
+ if (NeedsDWARF)
+ return make_error<JITLinkError>(
+ "In " + G.getName() + ", compact unwind recard ot " +
+ formatv("{0:x}", B->getAddress()) +
+ " needs DWARF, but no FDE was found");
+ }
+ } else {
+ if (NeedsDWARF)
+ return make_error<JITLinkError>(
+ "In " + G.getName() + ", compact unwind recard ot " +
+ formatv("{0:x}", B->getAddress()) + " needs DWARF, but no " +
+ EHFrameSectionName + " section exists");
+ }
+
+ if (!KeepAliveAlreadyPresent) {
+ // No FDE edge. We'll need to add a new edge from the function back
+ // to the CU record.
+ Fn.getBlock().addEdge(Edge::KeepAlive, 0, CURecSym, 0);
+ }
+ }
+
+ return Error::success();
+ }
+
+ /// Process all __compact_unwind records and reserve space for __unwind_info.
+ Error processAndReserveUnwindInfo(LinkGraph &G) {
+ // Bail out early if no unwind info.
+ Section *CUSec = G.findSectionByName(CompactUnwindSectionName);
+ if (!CUSec)
+ return Error::success();
+
+ // The __LD/__compact_unwind section is only used as input for the linker.
+ // We'll create a new __TEXT,__unwind_info section for unwind info output.
+ CUSec->setMemLifetime(orc::MemLifetime::NoAlloc);
+
+ // Find / make a mach-header to act as the base for unwind-info offsets
+ // (and to report the arch / subarch to libunwind).
+ if (auto Err = getOrCreateCompactUnwindBase(G))
+ return Err;
+
+ // Error out if there's already unwind-info in the graph: We have no idea
+ // how to merge unwind-info sections.
+ if (G.findSectionByName(UnwindInfoSectionName))
+ return make_error<JITLinkError>("In " + G.getName() + ", " +
+ UnwindInfoSectionName +
+ " already exists");
+
+ // Process the __compact_unwind section to build the Records vector that
+ // we'll use for writing the __unwind_info section.
+ if (auto Err = processCompactUnwind(G, *CUSec))
+ return Err;
+
+ // Calculate the size of __unwind_info.
+ size_t UnwindInfoSectionSize =
+ UnwindInfoSectionHeaderSize +
+ Personalities.size() * PersonalityEntrySize +
+ (NumSecondLevelPages + 1) * IndexEntrySize + NumLSDAs * LSDAEntrySize +
+ NumSecondLevelPages * SecondLevelPageHeaderSize +
+ Records.size() * SecondLevelPageEntrySize;
+
+ LLVM_DEBUG({
+ dbgs() << "In " << G.getName() << ", reserving "
+ << formatv("{0:x}", UnwindInfoSectionSize) << " bytes for "
+ << UnwindInfoSectionName << "\n";
+ });
+
+ // Create the __unwind_info section and reserve space for it.
+ Section &UnwindInfoSec =
+ G.createSection(UnwindInfoSectionName, orc::MemProt::Read);
+
+ auto UnwindInfoSectionContent = G.allocateBuffer(UnwindInfoSectionSize);
+ memset(UnwindInfoSectionContent.data(), 0, UnwindInfoSectionContent.size());
+ auto &B = G.createMutableContentBlock(
+ UnwindInfoSec, UnwindInfoSectionContent, orc::ExecutorAddr(), 8, 0);
+
+ // Add Keep-alive edges from the __unwind_info block to all of the target
+ // functions.
+ for (auto &R : Records)
+ B.addEdge(Edge::KeepAlive, 0, *R.Fn, 0);
+
+ return Error::success();
+ }
+
+ Error writeUnwindInfo(LinkGraph &G) {
+ Section *CUSec = G.findSectionByName(CompactUnwindSectionName);
+ if (!CUSec || CUSec->empty())
+ return Error::success();
+
+ Section *UnwindInfoSec = G.findSectionByName(UnwindInfoSectionName);
+ if (!UnwindInfoSec)
+ return make_error<JITLinkError>("In " + G.getName() + ", " +
+ UnwindInfoSectionName +
+ " missing after allocation");
+
+ if (UnwindInfoSec->blocks_size() != 1)
+ return make_error<JITLinkError>(
+ "In " + G.getName() + ", " + UnwindInfoSectionName +
+ " contains more than one block post-allocation");
+
+ LLVM_DEBUG(
+ { dbgs() << "Writing unwind info for " << G.getName() << "...\n"; });
+
+ mergeRecords();
+
+ auto &UnwindInfoBlock = **UnwindInfoSec->blocks().begin();
+ auto Content = UnwindInfoBlock.getMutableContent(G);
+ BinaryStreamWriter Writer(
+ {reinterpret_cast<uint8_t *>(Content.data()), Content.size()},
+ CURecTraits::Endianness);
+
+ // __unwind_info format, from mach-o/compact_unwind_encoding.h on Darwin:
+ //
+ // #define UNWIND_SECTION_VERSION 1
+ // struct unwind_info_section_header
+ // {
+ // uint32_t version; // UNWIND_SECTION_VERSION
+ // uint32_t commonEncodingsArraySectionOffset;
+ // uint32_t commonEncodingsArrayCount;
+ // uint32_t personalityArraySectionOffset;
+ // uint32_t personalityArrayCount;
+ // uint32_t indexSectionOffset;
+ // uint32_t indexCount;
+ // // compact_unwind_encoding_t[]
+ // // uint32_t personalities[]
+ // // unwind_info_section_header_index_entry[]
+ // // unwind_info_section_header_lsda_index_entry[]
+ // };
+
+ if (auto Err = writeHeader(G, Writer))
+ return Err;
+
+ // Skip common encodings: JITLink doesn't use them.
+
+ if (auto Err = writePersonalities(G, Writer))
+ return Err;
+
+ // Calculate the offset to the LSDAs.
+ size_t SectionOffsetToLSDAs =
+ Writer.getOffset() + (NumSecondLevelPages + 1) * IndexEntrySize;
+
+ // Calculate offset to the 1st second-level page.
+ size_t SectionOffsetToSecondLevelPages =
+ SectionOffsetToLSDAs + NumLSDAs * LSDAEntrySize;
+
+ if (auto Err = writeIndexes(G, Writer, SectionOffsetToLSDAs,
+ SectionOffsetToSecondLevelPages))
+ return Err;
+
+ if (auto Err = writeLSDAs(G, Writer))
+ return Err;
+
+ if (auto Err = writeSecondLevelPages(G, Writer))
+ return Err;
+
+ LLVM_DEBUG({
+ dbgs() << " Wrote " << formatv("{0:x}", Writer.getOffset())
+ << " bytes of unwind info.\n";
+ });
+
+ return Error::success();
+ }
+
+private:
+ // Calculate the size of unwind-info.
+ static constexpr size_t MaxPersonalities = 4;
+ static constexpr size_t PersonalityShift = 28;
+
+ static constexpr size_t UnwindInfoSectionHeaderSize = 4 * 7;
+ static constexpr size_t PersonalityEntrySize = 4;
+ static constexpr size_t IndexEntrySize = 3 * 4;
+ static constexpr size_t LSDAEntrySize = 2 * 4;
+ static constexpr size_t SecondLevelPageSize = 4096;
+ static constexpr size_t SecondLevelPageHeaderSize = 8;
+ static constexpr size_t SecondLevelPageEntrySize = 8;
+ static constexpr size_t NumRecordsPerSecondLevelPage =
+ (SecondLevelPageSize - SecondLevelPageHeaderSize) /
+ SecondLevelPageEntrySize;
+
+ struct CompactUnwindRecord {
+ Symbol *Fn = nullptr;
+ uint32_t Size = 0;
+ uint32_t Encoding = 0;
+ Symbol *LSDA = nullptr;
+ Symbol *FDE = nullptr;
+ };
+
+ Error processCompactUnwind(LinkGraph &G, Section &CUSec) {
+ // TODO: Reset NumLSDAs, Personalities and CompactUnwindRecords if
+ // processing more than once.
+ assert(NumLSDAs == 0 && "NumLSDAs should be zero");
+ assert(Records.empty() && "CompactUnwindRecords vector should be empty.");
+ assert(Personalities.empty() && "Personalities vector should be empty.");
+
+ SmallVector<CompactUnwindRecord> NonUniquedRecords;
+ NonUniquedRecords.reserve(CUSec.blocks_size());
+
+ // Process __compact_unwind blocks.
+ for (auto *B : CUSec.blocks()) {
+ CompactUnwindRecord R;
+ R.Encoding = CURecTraits::readEncoding(B->getContent());
+ for (auto &E : B->edges()) {
+ switch (E.getOffset()) {
+ case CURecTraits::FnFieldOffset:
+ // This could be the function-pointer, or the FDE keep-alive. Check
+ // the type to decide.
+ if (E.getKind() == Edge::KeepAlive)
+ R.FDE = &E.getTarget();
+ else
+ R.Fn = &E.getTarget();
+ break;
+ case CURecTraits::PersonalityFieldOffset: {
+ // Add the Personality to the Personalities map and update the
+ // encoding.
+ size_t PersonalityIdx = 0;
+ for (; PersonalityIdx != Personalities.size(); ++PersonalityIdx)
+ if (Personalities[PersonalityIdx] == &E.getTarget())
+ break;
+ if (PersonalityIdx == MaxPersonalities)
+ return make_error<JITLinkError>(
+ "In " + G.getName() +
+ ", __compact_unwind contains too many personalities (max " +
+ formatv("{}", MaxPersonalities) + ")");
+ if (PersonalityIdx == Personalities.size())
+ Personalities.push_back(&E.getTarget());
+
+ R.Encoding |= (PersonalityIdx + 1) << PersonalityShift;
+ break;
+ }
+ case CURecTraits::LSDAFieldOffset:
+ ++NumLSDAs;
+ R.LSDA = &E.getTarget();
+ break;
+ default:
+ return make_error<JITLinkError>("In " + G.getName() +
+ ", compact unwind record at " +
+ formatv("{0:x}", B->getAddress()) +
+ " has unrecognized edge at offset " +
+ formatv("{0:x}", E.getOffset()));
+ }
+ }
+ Records.push_back(R);
+ }
+
+ // Sort the records into ascending order.
+ llvm::sort(Records, [](const CompactUnwindRecord &LHS,
+ const CompactUnwindRecord &RHS) {
+ return LHS.Fn->getAddress() < RHS.Fn->getAddress();
+ });
+
+ // Calculate the number of second-level pages required.
+ NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) /
+ NumRecordsPerSecondLevelPage;
+
+ // Convert personality symbols to GOT entry pointers.
+ typename CURecTraits::GOTManager GOT(G);
+ for (auto &Personality : Personalities)
+ Personality = &GOT.getEntryForTarget(G, *Personality);
+
+ LLVM_DEBUG({
+ dbgs() << " In " << G.getName() << ", " << CompactUnwindSectionName
+ << ": raw records = " << Records.size()
+ << ", personalities = " << Personalities.size()
+ << ", lsdas = " << NumLSDAs << "\n";
+ });
+
+ return Error::success();
+ }
+
+ void mergeRecords() {
+ SmallVector<CompactUnwindRecord> NonUniqued = std::move(Records);
+ Records.reserve(NonUniqued.size());
+
+ Records.push_back(NonUniqued.front());
+ for (size_t I = 1; I != NonUniqued.size(); ++I) {
+ auto &Next = NonUniqued[I];
+ auto &Last = Records.back();
+
+ bool NextNeedsDWARF = CURecTraits::encodingSpecifiesDWARF(Next.Encoding);
+ bool CannotBeMerged = CURecTraits::encodingCannotBeMerged(Next.Encoding);
+ if (NextNeedsDWARF || (Next.Encoding != Last.Encoding) ||
+ CannotBeMerged || Next.LSDA || Last.LSDA)
+ Records.push_back(Next);
+ }
+
+ // Recalculate derived values that may have changed.
+ NumSecondLevelPages = (Records.size() + NumRecordsPerSecondLevelPage - 1) /
+ NumRecordsPerSecondLevelPage;
+ }
+
+ Error writeHeader(LinkGraph &G, BinaryStreamWriter &W) {
+ if (!isUInt<32>(NumSecondLevelPages + 1))
+ return make_error<JITLinkError>("In " + G.getName() + ", too many " +
+ UnwindInfoSectionName +
+ "second-level pages required");
+
+ // Write __unwind_info header.
+ size_t IndexArrayOffset = UnwindInfoSectionHeaderSize +
+ Personalities.size() * PersonalityEntrySize;
+
+ cantFail(W.writeInteger<uint32_t>(1));
+ cantFail(W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize));
+ cantFail(W.writeInteger<uint32_t>(0));
+ cantFail(W.writeInteger<uint32_t>(UnwindInfoSectionHeaderSize));
+ cantFail(W.writeInteger<uint32_t>(Personalities.size()));
+ cantFail(W.writeInteger<uint32_t>(IndexArrayOffset));
+ cantFail(W.writeInteger<uint32_t>(NumSecondLevelPages + 1));
+
+ return Error::success();
+ }
+
+ Error writePersonalities(LinkGraph &G, BinaryStreamWriter &W) {
+ // Write personalities.
+ for (auto *PSym : Personalities) {
+ auto Delta = PSym->getAddress() - CompactUnwindBase->getAddress();
+ if (!isUInt<32>(Delta))
+ return makePersonalityRangeError(G, *PSym);
+ cantFail(W.writeInteger<uint32_t>(Delta));
+ }
+ return Error::success();
+ }
+
+ Error writeIndexes(LinkGraph &G, BinaryStreamWriter &W,
+ size_t SectionOffsetToLSDAs,
+ size_t SectionOffsetToSecondLevelPages) {
+ // Assume that function deltas are ok in this method -- we'll error
+ // check all of them when we write the second level pages.
+
+ // Write the header index entries.
+ size_t RecordIdx = 0;
+ size_t NumPreviousLSDAs = 0;
+ for (auto &R : Records) {
+ // If this record marks the start of a new second level page.
+ if (RecordIdx % NumRecordsPerSecondLevelPage == 0) {
+ auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress();
+ auto SecondLevelPageOffset = SectionOffsetToSecondLevelPages +
+ (RecordIdx / NumRecordsPerSecondLevelPage);
+ auto LSDAOffset =
+ SectionOffsetToLSDAs + NumPreviousLSDAs * LSDAEntrySize;
+
+ cantFail(W.writeInteger<uint32_t>(FnDelta));
+ cantFail(W.writeInteger<uint32_t>(SecondLevelPageOffset));
+ cantFail(W.writeInteger<uint32_t>(LSDAOffset));
+ }
+ if (R.LSDA)
+ ++NumPreviousLSDAs;
+ ++RecordIdx;
+ }
+
+ // Write the index array terminator.
+ {
+ auto FnEndDelta =
+ Records.back().Fn->getRange().End - CompactUnwindBase->getAddress();
+
+ if (LLVM_UNLIKELY(!isUInt<32>(FnEndDelta)))
+ return make_error<JITLinkError>(
+ "In " + G.getName() + " " + UnwindInfoSectionName +
+ ", delta to end of functions " +
+ formatv("{0:x}", Records.back().Fn->getRange().End) +
+ " exceeds 32 bits");
+
+ cantFail(W.writeInteger<uint32_t>(FnEndDelta));
+ cantFail(W.writeInteger<uint32_t>(0));
+ cantFail(W.writeInteger<uint32_t>(SectionOffsetToSecondLevelPages));
+ }
+
+ return Error::success();
+ }
+
+ Error writeLSDAs(LinkGraph &G, BinaryStreamWriter &W) {
+ // As with writeIndexes, assume that function deltas are ok for now.
+ for (auto &R : Records) {
+ if (R.LSDA) {
+ auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress();
+ auto LSDADelta = R.LSDA->getAddress() - CompactUnwindBase->getAddress();
+
+ if (LLVM_UNLIKELY(!isUInt<32>(LSDADelta)))
+ return make_error<JITLinkError>(
+ "In " + G.getName() + " " + UnwindInfoSectionName +
+ ", delta to lsda at " + formatv("{0:x}", R.LSDA->getAddress()) +
+ " exceeds 32 bits");
+
+ cantFail(W.writeInteger<uint32_t>(FnDelta));
+ cantFail(W.writeInteger<uint32_t>(LSDADelta));
+ }
+ }
+
+ return Error::success();
+ }
+
+ Error writeSecondLevelPages(LinkGraph &G, BinaryStreamWriter &W) {
+ size_t RecordIdx = 0;
+
+ for (auto &R : Records) {
+ // When starting a new second-level page, write the page header:
+ //
+ // 2 : uint32_t -- UNWIND_SECOND_LEVEL_REGULAR
+ // 8 : uint16_t -- size of second level page table header
+ // count : uint16_t -- num entries in this second-level page
+ if (RecordIdx % NumRecordsPerSecondLevelPage == 0) {
+ constexpr uint32_t SecondLevelPageHeaderKind = 2;
+ constexpr uint16_t SecondLevelPageHeaderSize = 8;
+ uint16_t SecondLevelPageNumEntries =
+ std::min(Records.size() - RecordIdx, NumRecordsPerSecondLevelPage);
+
+ cantFail(W.writeInteger<uint32_t>(SecondLevelPageHeaderKind));
+ cantFail(W.writeInteger<uint16_t>(SecondLevelPageHeaderSize));
+ cantFail(W.writeInteger<uint16_t>(SecondLevelPageNumEntries));
+ }
+
+ // Write entry.
+ auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress();
+
+ if (LLVM_UNLIKELY(!isUInt<32>(FnDelta)))
+ return make_error<JITLinkError>(
+ "In " + G.getName() + " " + UnwindInfoSectionName +
+ ", delta to function at " + formatv("{0:x}", R.Fn->getAddress()) +
+ " exceeds 32 bits");
+
+ cantFail(W.writeInteger<uint32_t>(FnDelta));
+ cantFail(W.writeInteger<uint32_t>(R.Encoding));
+
+ ++RecordIdx;
+ }
+
+ return Error::success();
+ }
+
+ Error getOrCreateCompactUnwindBase(LinkGraph &G) {
+ auto Name = G.intern("__jitlink$libunwind_dso_base");
+ CompactUnwindBase = G.findAbsoluteSymbolByName(Name);
+ if (!CompactUnwindBase) {
+ if (auto LocalCUBase = getOrCreateLocalMachOHeader(G)) {
+ CompactUnwindBase = &*LocalCUBase;
+ auto &B = LocalCUBase->getBlock();
+ G.addDefinedSymbol(B, 0, *Name, B.getSize(), Linkage::Strong,
+ Scope::Local, false, true);
+ } else
+ return LocalCUBase.takeError();
+ }
+ CompactUnwindBase->setLive(true);
+ return Error::success();
+ }
+
+ Error makePersonalityRangeError(LinkGraph &G, Symbol &PSym) {
+ std::string ErrMsg;
+ {
+ raw_string_ostream ErrStream(ErrMsg);
+ ErrStream << "In " << G.getName() << " " << UnwindInfoSectionName
+ << ", personality ";
+ if (PSym.hasName())
+ ErrStream << PSym.getName() << " ";
+ ErrStream << "at " << PSym.getAddress()
+ << " is out of 32-bit delta range of compact-unwind base at "
+ << CompactUnwindBase->getAddress();
+ }
+ return make_error<JITLinkError>(std::move(ErrMsg));
+ }
+
+ StringRef CompactUnwindSectionName;
+ StringRef UnwindInfoSectionName;
+ StringRef EHFrameSectionName;
+ Symbol *CompactUnwindBase = nullptr;
+
+ size_t NumLSDAs = 0;
+ size_t NumSecondLevelPages = 0;
+ SmallVector<Symbol *, MaxPersonalities> Personalities;
+ SmallVector<CompactUnwindRecord> Records;
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#undef DEBUG_TYPE
+
+#endif // LIB_EXECUTIONENGINE_JITLINK_COMPACTUNWINDSUPPORTIMPL_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
index 3e757f780b550e7..179e458c3cd1f27 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.cpp
@@ -733,121 +733,5 @@ Error MachOLinkGraphBuilder::graphifyCStringSection(
return Error::success();
}
-Error CompactUnwindSplitter::operator()(LinkGraph &G) {
- auto *CUSec = G.findSectionByName(CompactUnwindSectionName);
- if (!CUSec)
- return Error::success();
-
- if (!G.getTargetTriple().isOSBinFormatMachO())
- return make_error<JITLinkError>(
- "Error linking " + G.getName() +
- ": compact unwind splitting not supported on non-macho target " +
- G.getTargetTriple().str());
-
- unsigned CURecordSize = 0;
- unsigned PersonalityEdgeOffset = 0;
- unsigned LSDAEdgeOffset = 0;
- switch (G.getTargetTriple().getArch()) {
- case Triple::aarch64:
- case Triple::x86_64:
- // 64-bit compact-unwind record format:
- // Range start: 8 bytes.
- // Range size: 4 bytes.
- // CU encoding: 4 bytes.
- // Personality: 8 bytes.
- // LSDA: 8 bytes.
- CURecordSize = 32;
- PersonalityEdgeOffset = 16;
- LSDAEdgeOffset = 24;
- break;
- default:
- return make_error<JITLinkError>(
- "Error linking " + G.getName() +
- ": compact unwind splitting not supported on " +
- G.getTargetTriple().getArchName());
- }
-
- std::vector<Block *> OriginalBlocks(CUSec->blocks().begin(),
- CUSec->blocks().end());
- LLVM_DEBUG({
- dbgs() << "In " << G.getName() << " splitting compact unwind section "
- << CompactUnwindSectionName << " containing "
- << OriginalBlocks.size() << " initial blocks...\n";
- });
-
- while (!OriginalBlocks.empty()) {
- auto *B = OriginalBlocks.back();
- OriginalBlocks.pop_back();
-
- if (B->getSize() == 0) {
- LLVM_DEBUG({
- dbgs() << " Skipping empty block at "
- << formatv("{0:x16}", B->getAddress()) << "\n";
- });
- continue;
- }
-
- unsigned NumBlocks = B->getSize() / CURecordSize;
-
- LLVM_DEBUG({
- dbgs() << " Splitting block at " << formatv("{0:x16}", B->getAddress())
- << " into " << NumBlocks << " compact unwind record(s)\n";
- });
-
- if (B->getSize() % CURecordSize)
- return make_error<JITLinkError>(
- "Error splitting compact unwind record in " + G.getName() +
- ": block at " + formatv("{0:x}", B->getAddress()) + " has size " +
- formatv("{0:x}", B->getSize()) +
- " (not a multiple of CU record size of " +
- formatv("{0:x}", CURecordSize) + ")");
-
- auto Blocks =
- G.splitBlock(*B, map_range(seq(1U, NumBlocks), [=](Edge::OffsetT Idx) {
- return Idx * CURecordSize;
- }));
-
- for (auto *CURec : Blocks) {
- bool AddedKeepAlive = false;
-
- for (auto &E : CURec->edges()) {
- if (E.getOffset() == 0) {
- LLVM_DEBUG({
- dbgs() << " Updating compact unwind record at "
- << CURec->getAddress() << " to point to "
- << (E.getTarget().hasName() ? *E.getTarget().getName()
- : StringRef())
- << " (at " << E.getTarget().getAddress() << ")\n";
- });
-
- if (E.getTarget().isExternal())
- return make_error<JITLinkError>(
- "Error adding keep-alive edge for compact unwind record at " +
- formatv("{0:x}", CURec->getAddress()) + ": target " +
- *E.getTarget().getName() + " is an external symbol");
- auto &TgtBlock = E.getTarget().getBlock();
- auto &CURecSym =
- G.addAnonymousSymbol(*CURec, 0, CURecordSize, false, false);
- TgtBlock.addEdge(Edge::KeepAlive, 0, CURecSym, 0);
- AddedKeepAlive = true;
- } else if (E.getOffset() != PersonalityEdgeOffset &&
- E.getOffset() != LSDAEdgeOffset)
- return make_error<JITLinkError>(
- "Unexpected edge at offset " + formatv("{0:x}", E.getOffset()) +
- " in compact unwind record at " +
- formatv("{0:x}", CURec->getAddress()));
- }
-
- if (!AddedKeepAlive)
- return make_error<JITLinkError>(
- "Error adding keep-alive edge for compact unwind record at " +
- formatv("{0:x}", CURec->getAddress()) +
- ": no outgoing target edge at offset 0");
- }
- }
-
- return Error::success();
-}
-
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
index 6afa01250f62d67..343218ec9ad1889 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/MachOLinkGraphBuilder.h
@@ -236,17 +236,6 @@ class MachOLinkGraphBuilder {
StringMap<SectionParserFunction> CustomSectionParserFunctions;
};
-/// A pass to split up __LD,__compact_unwind sections.
-class CompactUnwindSplitter {
-public:
- CompactUnwindSplitter(StringRef CompactUnwindSectionName)
- : CompactUnwindSectionName(CompactUnwindSectionName) {}
- Error operator()(LinkGraph &G);
-
-private:
- StringRef CompactUnwindSectionName;
-};
-
} // end namespace jitlink
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index 29061fff9c2aea4..4860db4f5eb37c6 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -13,7 +13,9 @@
#include "llvm/ExecutionEngine/JITLink/MachO_arm64.h"
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
+#include "CompactUnwindSupport.h"
#include "DefineExternalSectionStartAndEndSymbols.h"
#include "MachOLinkGraphBuilder.h"
@@ -625,6 +627,27 @@ static Error applyPACSigningToModInitPointers(LinkGraph &G) {
return Error::success();
}
+struct CompactUnwindTraits_MachO_arm64
+ : public CompactUnwindTraits<CompactUnwindTraits_MachO_arm64,
+ /* PointerSize = */ 8> {
+ // FIXME: Reinstate once we no longer need the MSVC workaround. See
+ // FIXME for CompactUnwindTraits in CompactUnwindSupport.h.
+ // constexpr static size_t PointerSize = 8;
+
+ constexpr static endianness Endianness = endianness::little;
+
+ constexpr static uint32_t EncodingModeMask = 0x0f000000;
+
+ using GOTManager = aarch64::GOTTableManager;
+
+ static bool encodingSpecifiesDWARF(uint32_t Encoding) {
+ constexpr uint32_t DWARFMode = 0x03000000;
+ return (Encoding & EncodingModeMask) == DWARFMode;
+ }
+
+ static bool encodingCannotBeMerged(uint32_t Encoding) { return false; }
+};
+
void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
@@ -637,16 +660,21 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
- // Add compact unwind splitter pass.
- Config.PrePrunePasses.push_back(
- CompactUnwindSplitter("__LD,__compact_unwind"));
-
// Add eh-frame passes.
- // FIXME: Prune eh-frames for which compact-unwind is available once
- // we support compact-unwind registration with libunwind.
Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_arm64());
Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_arm64());
+ // Create a compact-unwind manager for use in passes below.
+ auto CompactUnwindMgr =
+ std::make_shared<CompactUnwindManager<CompactUnwindTraits_MachO_arm64>>(
+ orc::MachOCompactUnwindSectionName, orc::MachOUnwindInfoSectionName,
+ orc::MachOEHFrameSectionName);
+
+ // Add compact unwind prepare pass.
+ Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->prepareForPrune(G);
+ });
+
// Resolve any external section start / end symbols.
Config.PostAllocationPasses.push_back(
createDefineExternalSectionStartAndEndSymbolsPass(
@@ -663,6 +691,16 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
Config.PreFixupPasses.push_back(
aarch64::lowerPointer64AuthEdgesToSigningFunction);
}
+
+ // Reserve unwind-info space.
+ Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->processAndReserveUnwindInfo(G);
+ });
+
+ // Translate compact-unwind to unwind-info.
+ Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->writeUnwindInfo(G);
+ });
}
if (auto Err = Ctx->modifyPassConfig(*G, Config))
@@ -673,11 +711,11 @@ void link_MachO_arm64(std::unique_ptr<LinkGraph> G,
}
LinkGraphPassFunction createEHFrameSplitterPass_MachO_arm64() {
- return DWARFRecordSectionSplitter("__TEXT,__eh_frame");
+ return DWARFRecordSectionSplitter(orc::MachOEHFrameSectionName);
}
LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_arm64() {
- return EHFrameEdgeFixer("__TEXT,__eh_frame", aarch64::PointerSize,
+ return EHFrameEdgeFixer(orc::MachOEHFrameSectionName, aarch64::PointerSize,
aarch64::Pointer32, aarch64::Pointer64,
aarch64::Delta32, aarch64::Delta64,
aarch64::NegDelta32);
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
index 9547266dc978920..d56dfdc07636dfe 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp
@@ -13,7 +13,9 @@
#include "llvm/ExecutionEngine/JITLink/MachO_x86_64.h"
#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
+#include "CompactUnwindSupport.h"
#include "DefineExternalSectionStartAndEndSymbols.h"
#include "MachOLinkGraphBuilder.h"
@@ -500,26 +502,57 @@ Expected<std::unique_ptr<LinkGraph>> createLinkGraphFromMachOObject_x86_64(
.buildGraph();
}
+struct CompactUnwindTraits_MachO_x86_64
+ : public CompactUnwindTraits<CompactUnwindTraits_MachO_x86_64,
+ /* PointerSize = */ 8> {
+ // FIXME: Reinstate once we no longer need the MSVC workaround. See
+ // FIXME for CompactUnwindTraits in CompactUnwindSupport.h.
+ // constexpr static size_t PointerSize = 8;
+
+ constexpr static endianness Endianness = endianness::little;
+
+ constexpr static uint32_t EncodingModeMask = 0x0f000000;
+
+ using GOTManager = x86_64::GOTTableManager;
+
+ static bool encodingSpecifiesDWARF(uint32_t Encoding) {
+ constexpr uint32_t DWARFMode = 0x04000000;
+ return (Encoding & EncodingModeMask) == DWARFMode;
+ }
+
+ static bool encodingCannotBeMerged(uint32_t Encoding) {
+ constexpr uint32_t StackIndirectMode = 0x03000000;
+ return (Encoding & EncodingModeMask) == StackIndirectMode;
+ }
+};
+
void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
std::unique_ptr<JITLinkContext> Ctx) {
PassConfiguration Config;
if (Ctx->shouldAddDefaultTargetPasses(G->getTargetTriple())) {
- // Add eh-frame passes.
- Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64());
- Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64());
-
- // Add compact unwind splitter pass.
- Config.PrePrunePasses.push_back(
- CompactUnwindSplitter("__LD,__compact_unwind"));
-
// Add a mark-live pass.
if (auto MarkLive = Ctx->getMarkLivePass(G->getTargetTriple()))
Config.PrePrunePasses.push_back(std::move(MarkLive));
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
+ // Add eh-frame passes.
+ Config.PrePrunePasses.push_back(createEHFrameSplitterPass_MachO_x86_64());
+ Config.PrePrunePasses.push_back(createEHFrameEdgeFixerPass_MachO_x86_64());
+
+ // Create a compact-unwind manager for use in passes below.
+ auto CompactUnwindMgr = std::make_shared<
+ CompactUnwindManager<CompactUnwindTraits_MachO_x86_64>>(
+ orc::MachOCompactUnwindSectionName, orc::MachOUnwindInfoSectionName,
+ orc::MachOEHFrameSectionName);
+
+ // Add compact unwind prepare pass.
+ Config.PrePrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->prepareForPrune(G);
+ });
+
// Resolve any external section start / end symbols.
Config.PostAllocationPasses.push_back(
createDefineExternalSectionStartAndEndSymbolsPass(
@@ -528,6 +561,16 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
// Add an in-place GOT/Stubs pass.
Config.PostPrunePasses.push_back(buildGOTAndStubs_MachO_x86_64);
+ // Reserve space for unwind-info.
+ Config.PostPrunePasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->processAndReserveUnwindInfo(G);
+ });
+
+ // Translate compact-unwind to unwind-info.
+ Config.PreFixupPasses.push_back([CompactUnwindMgr](LinkGraph &G) {
+ return CompactUnwindMgr->writeUnwindInfo(G);
+ });
+
// Add GOT/Stubs optimizer pass.
Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses);
}
@@ -540,11 +583,11 @@ void link_MachO_x86_64(std::unique_ptr<LinkGraph> G,
}
LinkGraphPassFunction createEHFrameSplitterPass_MachO_x86_64() {
- return DWARFRecordSectionSplitter("__TEXT,__eh_frame");
+ return DWARFRecordSectionSplitter(orc::MachOEHFrameSectionName);
}
LinkGraphPassFunction createEHFrameEdgeFixerPass_MachO_x86_64() {
- return EHFrameEdgeFixer("__TEXT,__eh_frame", x86_64::PointerSize,
+ return EHFrameEdgeFixer(orc::MachOEHFrameSectionName, x86_64::PointerSize,
x86_64::Pointer32, x86_64::Pointer64, x86_64::Delta32,
x86_64::Delta64, x86_64::NegDelta32);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 2ab5d6dd39b6359..8a866294eee25e7 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -57,6 +57,7 @@ add_llvm_component_library(LLVMOrcJIT
ExecutorProcessControl.cpp
TaskDispatch.cpp
ThreadSafeModule.cpp
+ UnwindInfoRegistrationPlugin.cpp
RedirectionManager.cpp
JITLinkRedirectableSymbolManager.cpp
ReOptimizeLayer.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
index 5d2f3cd4a8be8a9..c4d65af1b57f844 100644
--- a/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/CompileUtils.cpp
@@ -33,6 +33,9 @@ irManglingOptionsFromTargetOptions(const TargetOptions &Opts) {
/// Compile a Module to an ObjectFile.
Expected<SimpleCompiler::CompileResult> SimpleCompiler::operator()(Module &M) {
+ if (M.getDataLayout().isDefault())
+ M.setDataLayout(TM.createDataLayout());
+
CompileResult CachedObject = tryToLoadFromObjectCache(M);
if (CachedObject)
return std::move(CachedObject);
diff --git a/llvm/lib/ExecutionEngine/Orc/Core.cpp b/llvm/lib/ExecutionEngine/Orc/Core.cpp
index d47eb4416d3c282..9f466e725668a27 100644
--- a/llvm/lib/ExecutionEngine/Orc/Core.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Core.cpp
@@ -1251,9 +1251,7 @@ JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
LinkOrder.push_back({this, JITDylibLookupFlags::MatchAllSymbols});
}
-std::pair<JITDylib::AsynchronousSymbolQuerySet,
- std::shared_ptr<SymbolDependenceMap>>
-JITDylib::IL_removeTracker(ResourceTracker &RT) {
+JITDylib::RemoveTrackerResult JITDylib::IL_removeTracker(ResourceTracker &RT) {
// Note: Should be called under the session lock.
assert(State != Closed && "JD is defunct");
@@ -1292,7 +1290,10 @@ JITDylib::IL_removeTracker(ResourceTracker &RT) {
SymbolsToFail.push_back(Sym);
}
- auto Result = ES.IL_failSymbols(*this, std::move(SymbolsToFail));
+ auto [QueriesToFail, FailedSymbols] =
+ ES.IL_failSymbols(*this, std::move(SymbolsToFail));
+
+ std::vector<std::unique_ptr<MaterializationUnit>> DefunctMUs;
// Removed symbols should be taken out of the table altogether.
for (auto &Sym : SymbolsToRemove) {
@@ -1302,7 +1303,12 @@ JITDylib::IL_removeTracker(ResourceTracker &RT) {
// Remove Materializer if present.
if (I->second.hasMaterializerAttached()) {
// FIXME: Should this discard the symbols?
- UnmaterializedInfos.erase(Sym);
+ auto J = UnmaterializedInfos.find(Sym);
+ assert(J != UnmaterializedInfos.end() &&
+ "Symbol table indicates MU present, but no UMI record");
+ if (J->second->MU)
+ DefunctMUs.push_back(std::move(J->second->MU));
+ UnmaterializedInfos.erase(J);
} else {
assert(!UnmaterializedInfos.count(Sym) &&
"Symbol has materializer attached");
@@ -1313,7 +1319,8 @@ JITDylib::IL_removeTracker(ResourceTracker &RT) {
shrinkMaterializationInfoMemory();
- return Result;
+ return {std::move(QueriesToFail), std::move(FailedSymbols),
+ std::move(DefunctMUs)};
}
void JITDylib::transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT) {
@@ -2180,16 +2187,17 @@ Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
});
std::vector<ResourceManager *> CurrentResourceManagers;
- JITDylib::AsynchronousSymbolQuerySet QueriesToFail;
- std::shared_ptr<SymbolDependenceMap> FailedSymbols;
+ JITDylib::RemoveTrackerResult R;
runSessionLocked([&] {
CurrentResourceManagers = ResourceManagers;
RT.makeDefunct();
- std::tie(QueriesToFail, FailedSymbols) =
- RT.getJITDylib().IL_removeTracker(RT);
+ R = RT.getJITDylib().IL_removeTracker(RT);
});
+ // Release any defunct MaterializationUnits.
+ R.DefunctMUs.clear();
+
Error Err = Error::success();
auto &JD = RT.getJITDylib();
@@ -2197,9 +2205,9 @@ Error ExecutionSession::removeResourceTracker(ResourceTracker &RT) {
Err = joinErrors(std::move(Err),
L->handleRemoveResources(JD, RT.getKeyUnsafe()));
- for (auto &Q : QueriesToFail)
- Q->handleFailed(
- make_error<FailedToMaterialize>(getSymbolStringPool(), FailedSymbols));
+ for (auto &Q : R.QueriesToFail)
+ Q->handleFailed(make_error<FailedToMaterialize>(getSymbolStringPool(),
+ R.FailedSymbols));
return Err;
}
diff --git a/llvm/lib/ExecutionEngine/Orc/EHFrameRegistrationPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/EHFrameRegistrationPlugin.cpp
index 217c693dae9c98b..161bd68ff085499 100644
--- a/llvm/lib/ExecutionEngine/Orc/EHFrameRegistrationPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/EHFrameRegistrationPlugin.cpp
@@ -9,6 +9,7 @@
#include "llvm/ExecutionEngine/Orc/EHFrameRegistrationPlugin.h"
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
#define DEBUG_TYPE "orc"
@@ -21,11 +22,19 @@ EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
: ES(ES), Registrar(std::move(Registrar)) {}
void EHFrameRegistrationPlugin::modifyPassConfig(
- MaterializationResponsibility &MR, LinkGraph &G,
+ MaterializationResponsibility &MR, LinkGraph &LG,
PassConfiguration &PassConfig) {
+ if (LG.getTargetTriple().isOSBinFormatMachO())
+ PassConfig.PrePrunePasses.insert(
+ PassConfig.PrePrunePasses.begin(), [](LinkGraph &G) {
+ if (auto *CUSec = G.findSectionByName(MachOCompactUnwindSectionName))
+ G.removeSection(*CUSec);
+ return Error::success();
+ });
+
PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
- G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
+ LG.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
if (Addr) {
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
assert(!InProcessLinks.count(&MR) &&
diff --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index aa799687e6d5d1d..b51fa24be76d1a1 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -45,6 +45,7 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
this->DylibMgr = this;
this->JDI = {ExecutorAddr::fromPtr(jitDispatchViaWrapperFunctionManager),
ExecutorAddr::fromPtr(this)};
+
if (this->TargetTriple.isOSBinFormatMachO())
GlobalManglingPrefix = '_';
@@ -52,6 +53,12 @@ SelfExecutorProcessControl::SelfExecutorProcessControl(
ExecutorAddr::fromPtr(&llvm_orc_registerEHFrameSectionWrapper);
this->BootstrapSymbols[rt::DeregisterEHFrameSectionWrapperName] =
ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
+
+#ifdef __APPLE__
+ this->UnwindInfoMgr = UnwindInfoManager::TryCreate();
+ if (this->UnwindInfoMgr)
+ this->UnwindInfoMgr->addBootstrapSymbols(this->BootstrapSymbols);
+#endif // __APPLE__
}
Expected<std::unique_ptr<SelfExecutorProcessControl>>
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 80500d0fdd9bcbf..938fe58ef85cfeb 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -21,6 +21,7 @@
#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
+#include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
@@ -1220,12 +1221,30 @@ Expected<JITDylibSP> setUpGenericLLVMIRPlatform(LLJIT &J) {
if (auto *OLL = dyn_cast<ObjectLinkingLayer>(&J.getObjLinkingLayer())) {
- auto &ES = J.getExecutionSession();
- if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES))
- OLL->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
- ES, std::move(*EHFrameRegistrar)));
- else
- return EHFrameRegistrar.takeError();
+ bool CompactUnwindInfoSupported = false;
+
+ // Enable compact-unwind support if possible.
+ if (J.getTargetTriple().isOSDarwin() ||
+ J.getTargetTriple().isOSBinFormatMachO()) {
+ if (auto UIRP = UnwindInfoRegistrationPlugin::Create(
+ J.getIRCompileLayer(), PlatformJD)) {
+ CompactUnwindInfoSupported = true;
+ OLL->addPlugin(std::move(*UIRP));
+ LLVM_DEBUG(dbgs() << "Enabled compact-unwind support.\n");
+ } else
+ consumeError(UIRP.takeError());
+ }
+
+ // Otherwise fall back to standard unwind registration.
+ if (!CompactUnwindInfoSupported) {
+ auto &ES = J.getExecutionSession();
+ if (auto EHFrameRegistrar = EPCEHFrameRegistrar::Create(ES)) {
+ OLL->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
+ ES, std::move(*EHFrameRegistrar)));
+ LLVM_DEBUG(dbgs() << "Enabled eh-frame support.\n");
+ } else
+ return EHFrameRegistrar.takeError();
+ }
}
J.setPlatformSupport(
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
index d94acf276881771..53488b75a268620 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/MachOObjectFormat.cpp
@@ -18,6 +18,7 @@ namespace orc {
StringRef MachODataCommonSectionName = "__DATA,__common";
StringRef MachODataDataSectionName = "__DATA,__data";
StringRef MachOEHFrameSectionName = "__TEXT,__eh_frame";
+StringRef MachOCompactUnwindSectionName = "__LD,__compact_unwind";
StringRef MachOCStringSectionName = "__TEXT,__cstring";
StringRef MachOModInitFuncSectionName = "__DATA,__mod_init_func";
StringRef MachOObjCCatListSectionName = "__DATA,__objc_catlist";
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
index 54a25c007c589dc..fef3ff989a52ae1 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
@@ -64,5 +64,19 @@ const char *RunAsIntFunctionWrapperName =
"__llvm_orc_bootstrap_run_as_int_function_wrapper";
} // end namespace rt
+namespace rt_alt {
+const char *UnwindInfoManagerInstanceName =
+ "orc_rt_alt_UnwindInfoManager_Instance";
+const char *UnwindInfoManagerFindSectionsHelperName =
+ "orc_rt_alt_UnwindInfoManager_findSectionsHelper";
+const char *UnwindInfoManagerEnableWrapperName =
+ "orc_rt_alt_UnwindInfoManager_enable";
+const char *UnwindInfoManagerDisableWrapperName =
+ "orc_rt_alt_UnwindInfoManager_disable";
+const char *UnwindInfoManagerRegisterActionName =
+ "orc_rt_alt_UnwindInfoManager_register";
+const char *UnwindInfoManagerDeregisterActionName =
+ "orc_rt_alt_UnwindInfoManager_deregister";
+} // end namespace rt_alt
} // end namespace orc
} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
index 3d1dfe758c79ddf..ffc1bbfa121b393 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_component_library(LLVMOrcTargetProcess
SimpleExecutorMemoryManager.cpp
SimpleRemoteEPCServer.cpp
TargetExecutionUtils.cpp
+ UnwindInfoManager.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/ExecutionEngine/Orc
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp
new file mode 100644
index 000000000000000..9f748154c03e556
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.cpp
@@ -0,0 +1,188 @@
+//===------- UnwindInfoManager.cpp - Register unwind info sections --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/TargetProcess/UnwindInfoManager.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
+#include "llvm/Support/DynamicLibrary.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::shared;
+
+static orc::shared::CWrapperFunctionResult
+llvm_orc_rt_alt_UnwindInfoManager_enable(const char *Data, uint64_t Size) {
+ return WrapperFunction<SPSError(SPSExecutorAddr, SPSExecutorAddr)>::handle(
+ Data, Size,
+ [](ExecutorAddr Instance, ExecutorAddr FindFn) {
+ return Instance.toPtr<UnwindInfoManager *>()->enable(
+ FindFn.toPtr<void *>());
+ })
+ .release();
+}
+
+static orc::shared::CWrapperFunctionResult
+llvm_orc_rt_alt_UnwindInfoManager_disable(const char *Data, uint64_t Size) {
+ return WrapperFunction<SPSError(SPSExecutorAddr)>::handle(
+ Data, Size,
+ [](ExecutorAddr Instance) {
+ return Instance.toPtr<UnwindInfoManager *>()->disable();
+ })
+ .release();
+}
+
+static orc::shared::CWrapperFunctionResult
+llvm_orc_rt_alt_UnwindInfoManager_register(const char *Data, uint64_t Size) {
+ using SPSSig =
+ SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>,
+ SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange);
+
+ return WrapperFunction<SPSSig>::handle(
+ Data, Size,
+ [](ExecutorAddr Instance,
+ std::vector<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,
+ ExecutorAddrRange DWARFRange,
+ ExecutorAddrRange CompactUnwindRange) {
+ return Instance.toPtr<UnwindInfoManager *>()->registerSections(
+ CodeRanges, DSOBase, DWARFRange, CompactUnwindRange);
+ })
+ .release();
+}
+
+static orc::shared::CWrapperFunctionResult
+llvm_orc_rt_alt_UnwindInfoManager_deregister(const char *Data, uint64_t Size) {
+ using SPSSig = SPSError(SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>);
+
+ return WrapperFunction<SPSSig>::handle(
+ Data, Size,
+ [](ExecutorAddr Instance,
+ std::vector<ExecutorAddrRange> CodeRanges) {
+ return Instance.toPtr<UnwindInfoManager *>()->deregisterSections(
+ CodeRanges);
+ })
+ .release();
+}
+
+namespace llvm::orc {
+
+const char *UnwindInfoManager::AddFnName =
+ "__unw_add_find_dynamic_unwind_sections";
+const char *UnwindInfoManager::RemoveFnName =
+ "__unw_remove_find_dynamic_unwind_sections";
+
+std::unique_ptr<UnwindInfoManager> UnwindInfoManager::TryCreate() {
+ std::string ErrMsg;
+ auto DL = sys::DynamicLibrary::getPermanentLibrary(nullptr, &ErrMsg);
+ if (!DL.isValid())
+ return nullptr;
+
+ auto AddFindDynamicUnwindSections =
+ (int (*)(void *))DL.getAddressOfSymbol(AddFnName);
+ if (!AddFindDynamicUnwindSections)
+ return nullptr;
+
+ auto RemoveFindDynamicUnwindSections =
+ (int (*)(void *))DL.getAddressOfSymbol(RemoveFnName);
+ if (!RemoveFindDynamicUnwindSections)
+ return nullptr;
+
+ return std::unique_ptr<UnwindInfoManager>(new UnwindInfoManager(
+ AddFindDynamicUnwindSections, RemoveFindDynamicUnwindSections));
+}
+
+Error UnwindInfoManager::shutdown() { return Error::success(); }
+
+void UnwindInfoManager::addBootstrapSymbols(StringMap<ExecutorAddr> &M) {
+ M[rt_alt::UnwindInfoManagerInstanceName] = ExecutorAddr::fromPtr(this);
+ M[rt_alt::UnwindInfoManagerFindSectionsHelperName] =
+ ExecutorAddr::fromPtr(&findSectionsHelper);
+ M[rt_alt::UnwindInfoManagerEnableWrapperName] =
+ ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_enable);
+ M[rt_alt::UnwindInfoManagerDisableWrapperName] =
+ ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_disable);
+ M[rt_alt::UnwindInfoManagerRegisterActionName] =
+ ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_register);
+ M[rt_alt::UnwindInfoManagerDeregisterActionName] =
+ ExecutorAddr::fromPtr(llvm_orc_rt_alt_UnwindInfoManager_deregister);
+}
+
+Error UnwindInfoManager::enable(void *FindDynamicUnwindSections) {
+ LLVM_DEBUG(dbgs() << "Enabling UnwindInfoManager.\n");
+
+ if (auto Err = AddFindDynamicUnwindSections(FindDynamicUnwindSections))
+ return make_error<StringError>(Twine("Could not register function via ") +
+ AddFnName +
+ ", error code = " + Twine(Err),
+ inconvertibleErrorCode());
+
+ this->FindDynamicUnwindSections = FindDynamicUnwindSections;
+ return Error::success();
+}
+
+Error UnwindInfoManager::disable(void) {
+ LLVM_DEBUG(dbgs() << "Disabling UnwindInfoManager.\n");
+
+ if (FindDynamicUnwindSections)
+ if (auto Err = RemoveFindDynamicUnwindSections(FindDynamicUnwindSections))
+ return make_error<StringError>(
+ Twine("Could not deregister function via ") + RemoveFnName +
+ "error code = " + Twine(Err),
+ inconvertibleErrorCode());
+
+ FindDynamicUnwindSections = nullptr;
+ return Error::success();
+}
+
+Error UnwindInfoManager::registerSections(
+ ArrayRef<ExecutorAddrRange> CodeRanges, ExecutorAddr DSOBase,
+ ExecutorAddrRange DWARFEHFrame, ExecutorAddrRange CompactUnwind) {
+ std::lock_guard<std::mutex> Lock(M);
+ for (auto &R : CodeRanges)
+ UWSecs[R.Start.getValue()] =
+ UnwindSections{static_cast<uintptr_t>(DSOBase.getValue()),
+ static_cast<uintptr_t>(DWARFEHFrame.Start.getValue()),
+ static_cast<size_t>(DWARFEHFrame.size()),
+ static_cast<uintptr_t>(CompactUnwind.Start.getValue()),
+ static_cast<size_t>(CompactUnwind.size())};
+ return Error::success();
+}
+
+Error UnwindInfoManager::deregisterSections(
+ ArrayRef<ExecutorAddrRange> CodeRanges) {
+ std::lock_guard<std::mutex> Lock(M);
+ for (auto &R : CodeRanges) {
+ auto I = UWSecs.find(R.Start.getValue());
+ if (I == UWSecs.end())
+ return make_error<StringError>(
+ "No unwind-info sections registered for range " +
+ formatv("{0:x} - {1:x}", R.Start, R.End),
+ inconvertibleErrorCode());
+ UWSecs.erase(I);
+ }
+ return Error::success();
+}
+
+int UnwindInfoManager::findSections(uintptr_t Addr, UnwindSections *Info) {
+ std::lock_guard<std::mutex> Lock(M);
+ auto I = UWSecs.upper_bound(Addr);
+ if (I == UWSecs.begin())
+ return 0;
+ --I;
+ *Info = I->second;
+ return 1;
+}
+
+int UnwindInfoManager::findSectionsHelper(UnwindInfoManager *Instance,
+ uintptr_t Addr,
+ UnwindSections *Info) {
+ return Instance->findSections(Addr, Info);
+}
+
+} // namespace llvm::orc
diff --git a/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp
new file mode 100644
index 000000000000000..ae1f3f98269dbbb
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.cpp
@@ -0,0 +1,238 @@
+//===----- UnwindInfoRegistrationPlugin.cpp - libunwind registration ------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h"
+
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
+#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm::jitlink;
+
+static const char *FindDynamicUnwindSectionsFunctionName =
+ "_orc_rt_alt_find_dynamic_unwind_sections";
+
+namespace llvm::orc {
+
+Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
+UnwindInfoRegistrationPlugin::Create(IRLayer &IRL, JITDylib &PlatformJD,
+ ExecutorAddr Instance,
+ ExecutorAddr FindHelper,
+ ExecutorAddr Enable, ExecutorAddr Disable,
+ ExecutorAddr Register,
+ ExecutorAddr Deregister) {
+
+ auto &ES = IRL.getExecutionSession();
+
+ // Build bouncer module.
+ auto M = makeBouncerModule(ES);
+ if (!M)
+ return M.takeError();
+
+ auto BouncerRT = PlatformJD.createResourceTracker();
+ auto RemoveBouncerModule = make_scope_exit([&]() {
+ if (auto Err = BouncerRT->remove())
+ ES.reportError(std::move(Err));
+ });
+
+ if (auto Err = PlatformJD.define(absoluteSymbols(
+ {{ES.intern(rt_alt::UnwindInfoManagerInstanceName),
+ ExecutorSymbolDef(Instance, JITSymbolFlags())},
+ {ES.intern(rt_alt::UnwindInfoManagerFindSectionsHelperName),
+ ExecutorSymbolDef(FindHelper, JITSymbolFlags::Callable)}})))
+ return std::move(Err);
+
+ if (auto Err = IRL.add(BouncerRT, std::move(*M)))
+ return Err;
+
+ auto FindUnwindSections =
+ ES.lookup({&PlatformJD}, FindDynamicUnwindSectionsFunctionName);
+ if (!FindUnwindSections)
+ return FindUnwindSections.takeError();
+
+ using namespace shared;
+ using SPSEnableSig = SPSError(SPSExecutorAddr, SPSExecutorAddr);
+ Error CallErr = Error::success();
+ if (auto Err = ES.callSPSWrapper<SPSEnableSig>(
+ Enable, CallErr, Instance, FindUnwindSections->getAddress())) {
+ consumeError(std::move(CallErr));
+ return std::move(Err);
+ }
+
+ if (CallErr)
+ return std::move(CallErr);
+
+ RemoveBouncerModule.release();
+
+ return std::shared_ptr<UnwindInfoRegistrationPlugin>(
+ new UnwindInfoRegistrationPlugin(ES, Instance, Disable, Register,
+ Deregister));
+}
+
+Expected<std::shared_ptr<UnwindInfoRegistrationPlugin>>
+UnwindInfoRegistrationPlugin::Create(IRLayer &IRL, JITDylib &PlatformJD) {
+
+ ExecutorAddr Instance, FindHelper, Enable, Disable, Register, Deregister;
+
+ auto &EPC = IRL.getExecutionSession().getExecutorProcessControl();
+ if (auto Err = EPC.getBootstrapSymbols(
+ {{Instance, rt_alt::UnwindInfoManagerInstanceName},
+ {FindHelper, rt_alt::UnwindInfoManagerFindSectionsHelperName},
+ {Enable, rt_alt::UnwindInfoManagerEnableWrapperName},
+ {Disable, rt_alt::UnwindInfoManagerDisableWrapperName},
+ {Register, rt_alt::UnwindInfoManagerRegisterActionName},
+ {Deregister, rt_alt::UnwindInfoManagerDeregisterActionName}}))
+ return std::move(Err);
+
+ return Create(IRL, PlatformJD, Instance, FindHelper, Enable, Disable,
+ Register, Deregister);
+}
+
+UnwindInfoRegistrationPlugin::~UnwindInfoRegistrationPlugin() {
+ using namespace shared;
+ using SPSDisableSig = SPSError(SPSExecutorAddr);
+ Error CallErr = Error::success();
+ if (auto Err = ES.callSPSWrapper<SPSDisableSig>(Disable, CallErr, Instance)) {
+ consumeError(std::move(CallErr));
+ ES.reportError(std::move(Err));
+ }
+ if (CallErr)
+ ES.reportError(std::move(CallErr));
+}
+
+void UnwindInfoRegistrationPlugin::modifyPassConfig(
+ MaterializationResponsibility &MR, LinkGraph &G,
+ PassConfiguration &PassConfig) {
+
+ PassConfig.PostFixupPasses.push_back(
+ [this](LinkGraph &G) { return addUnwindInfoRegistrationActions(G); });
+}
+
+Expected<ThreadSafeModule>
+UnwindInfoRegistrationPlugin::makeBouncerModule(ExecutionSession &ES) {
+ auto Ctx = std::make_unique<LLVMContext>();
+ auto M = std::make_unique<Module>("__libunwind_find_unwind_bouncer", *Ctx);
+ M->setTargetTriple(ES.getTargetTriple().str());
+
+ auto EscapeName = [](const char *N) { return std::string("\01") + N; };
+
+ auto *PtrTy = PointerType::getUnqual(*Ctx);
+ auto *OpaqueStructTy = StructType::create(*Ctx, "UnwindInfoMgr");
+ auto *UnwindMgrInstance = new GlobalVariable(
+ *M, OpaqueStructTy, true, GlobalValue::ExternalLinkage, nullptr,
+ EscapeName(rt_alt::UnwindInfoManagerInstanceName));
+
+ auto *Int64Ty = Type::getInt64Ty(*Ctx);
+ auto *FindHelperTy = FunctionType::get(Int64Ty, {PtrTy, PtrTy, PtrTy}, false);
+ auto *FindHelperFn = Function::Create(
+ FindHelperTy, GlobalValue::ExternalLinkage,
+ EscapeName(rt_alt::UnwindInfoManagerFindSectionsHelperName), *M);
+
+ auto *FindFnTy = FunctionType::get(Int64Ty, {PtrTy, PtrTy}, false);
+ auto *FindFn =
+ Function::Create(FindFnTy, GlobalValue::ExternalLinkage,
+ EscapeName(FindDynamicUnwindSectionsFunctionName), *M);
+ auto *EntryBlock = BasicBlock::Create(M->getContext(), StringRef(), FindFn);
+ IRBuilder<> IB(EntryBlock);
+
+ std::vector<Value *> FindHelperArgs;
+ FindHelperArgs.push_back(UnwindMgrInstance);
+ for (auto &Arg : FindFn->args())
+ FindHelperArgs.push_back(&Arg);
+
+ IB.CreateRet(IB.CreateCall(FindHelperFn, FindHelperArgs));
+
+ return ThreadSafeModule(std::move(M), std::move(Ctx));
+}
+
+Error UnwindInfoRegistrationPlugin::addUnwindInfoRegistrationActions(
+ LinkGraph &G) {
+ ExecutorAddrRange EHFrameRange, UnwindInfoRange;
+
+ std::vector<Block *> CodeBlocks;
+
+ auto ScanUnwindInfoSection = [&](Section &Sec, ExecutorAddrRange &SecRange) {
+ if (Sec.empty())
+ return;
+
+ SecRange.Start = (*Sec.blocks().begin())->getAddress();
+ for (auto *B : Sec.blocks()) {
+ auto R = B->getRange();
+ SecRange.Start = std::min(SecRange.Start, R.Start);
+ SecRange.End = std::max(SecRange.End, R.End);
+ for (auto &E : B->edges()) {
+ if (E.getKind() != Edge::KeepAlive || !E.getTarget().isDefined())
+ continue;
+ auto &TargetBlock = E.getTarget().getBlock();
+ auto &TargetSection = TargetBlock.getSection();
+ if ((TargetSection.getMemProt() & MemProt::Exec) == MemProt::Exec)
+ CodeBlocks.push_back(&TargetBlock);
+ }
+ }
+ };
+
+ if (auto *EHFrame = G.findSectionByName(MachOEHFrameSectionName))
+ ScanUnwindInfoSection(*EHFrame, EHFrameRange);
+
+ if (auto *UnwindInfo = G.findSectionByName(MachOUnwindInfoSectionName))
+ ScanUnwindInfoSection(*UnwindInfo, UnwindInfoRange);
+
+ if (CodeBlocks.empty())
+ return Error::success();
+
+ if ((EHFrameRange == ExecutorAddrRange() &&
+ UnwindInfoRange == ExecutorAddrRange()))
+ return Error::success();
+
+ llvm::sort(CodeBlocks, [](const Block *LHS, const Block *RHS) {
+ return LHS->getAddress() < RHS->getAddress();
+ });
+
+ SmallVector<ExecutorAddrRange> CodeRanges;
+ for (auto *B : CodeBlocks) {
+ if (CodeRanges.empty() || CodeRanges.back().End != B->getAddress())
+ CodeRanges.push_back(B->getRange());
+ else
+ CodeRanges.back().End = B->getRange().End;
+ }
+
+ ExecutorAddr DSOBase;
+ if (auto *DSOBaseSym = G.findAbsoluteSymbolByName(DSOBaseName))
+ DSOBase = DSOBaseSym->getAddress();
+ else if (auto *DSOBaseSym = G.findExternalSymbolByName(DSOBaseName))
+ DSOBase = DSOBaseSym->getAddress();
+ else if (auto *DSOBaseSym = G.findDefinedSymbolByName(DSOBaseName))
+ DSOBase = DSOBaseSym->getAddress();
+ else
+ return make_error<StringError>("In " + G.getName() +
+ " could not find dso base symbol",
+ inconvertibleErrorCode());
+
+ using namespace shared;
+ using SPSRegisterArgs =
+ SPSArgList<SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>,
+ SPSExecutorAddr, SPSExecutorAddrRange, SPSExecutorAddrRange>;
+ using SPSDeregisterArgs =
+ SPSArgList<SPSExecutorAddr, SPSSequence<SPSExecutorAddrRange>>;
+
+ G.allocActions().push_back(
+ {cantFail(WrapperFunctionCall::Create<SPSRegisterArgs>(
+ Register, Instance, CodeRanges, DSOBase, EHFrameRange,
+ UnwindInfoRange)),
+ cantFail(WrapperFunctionCall::Create<SPSDeregisterArgs>(
+ Deregister, Instance, CodeRanges))});
+
+ return Error::success();
+}
+
+} // namespace llvm::orc
diff --git a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
index 1b8f45184833ffe..4ee55c61a81ea73 100644
--- a/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
+++ b/llvm/test/ExecutionEngine/Orc/minimal-throw-catch.ll
@@ -1,4 +1,4 @@
-; REQUIRES: x86_64-apple
+; REQUIRES: system-darwin && host-unwind-supports-jit
; RUN: lli -jit-kind=orc %s
;
; Basic correctness testing for eh-frame processing and registration.
diff --git a/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll b/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
index cd22ec65ed9996e..83d2d89a5d60704 100644
--- a/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
+++ b/llvm/test/ExecutionEngine/OrcLazy/minimal-throw-catch.ll
@@ -1,4 +1,4 @@
-; REQUIRES: x86_64-apple
+; REQUIRES: system-darwin && host-unwind-supports-jit
; RUN: lli -jit-kind=orc-lazy %s
;
; Basic correctness testing for eh-frame processing and registration.
diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py
index 3c0069d10412a5f..aad7a088551b297 100644
--- a/llvm/test/lit.cfg.py
+++ b/llvm/test/lit.cfg.py
@@ -566,6 +566,54 @@ def have_ld64_plugin_support():
if have_ld64_plugin_support():
config.available_features.add("ld64_plugin")
+def host_unwind_supports_jit():
+ # Do we expect the host machine to support JIT registration of clang's
+ # default unwind info format for the host (e.g. eh-frames, compact-unwind,
+ # etc.).
+
+ # Linux and the BSDs use DWARF eh-frames and all known unwinders support
+ # register_frame at minimum.
+ if platform.system() in [ "Linux", "FreeBSD", "NetBSD" ]:
+ return True
+
+ # Windows does not support frame info without the ORC runtime.
+ if platform.system() == "Windows":
+ return False
+
+ # On Darwin/x86-64 clang produces both eh-frames and compact-unwind, and
+ # libunwind supports register_frame. On Darwin/arm64 clang produces
+ # compact-unwind only, and JIT'd registration is not available before
+ # macOS 14.0.
+ if platform.system() == "Darwin":
+
+ assert (
+ "arm64" in config.host_triple
+ or "x86_64" in config.host_triple
+ )
+
+ if "x86_64" in config.host_triple:
+ return True
+
+ # Must be arm64. Check the macOS version.
+ try:
+ osx_version = subprocess.check_output(
+ ["sw_vers", "-productVersion"], universal_newlines=True
+ )
+ osx_version = tuple(int(x) for x in osx_version.split("."))
+ if len(osx_version) == 2:
+ osx_version = (osx_version[0], osx_version[1], 0)
+ if osx_version >= (14, 0):
+ return True
+ except:
+ pass
+
+ return False
+
+ return False
+
+if host_unwind_supports_jit():
+ config.available_features.add("host-unwind-supports-jit")
+
# Ask llvm-config about asserts
llvm_config.feature_config(
[
>From 06264d67d07132ecf244b7e119a66848a55fe55d Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 10:50:16 +1100
Subject: [PATCH 09/14] [ORC-RT] Add a comment explaining the purpose of this
testcase. NFC.
(cherry picked from commit aefa30e2301f155d4f4737d6f6c55c66eac58b2d)
---
compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
index 7e9c40c724aec6c..304588a32738604 100644
--- a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
+++ b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions.cpp
@@ -3,6 +3,7 @@
//
// REQUIRES: system-darwin && host-arch-compatible
+// Test that trivial throw / catch works.
int main(int argc, char *argv[]) {
try {
throw 42;
>From f865c5fe3a942d6b14a70767a5f2f78bda98db39 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 10:50:41 +1100
Subject: [PATCH 10/14] [ORC] Fix buggy calculation of second-level-page offset
in unwind-info.
SecondLevelPageOffset should be incremented by SecondLevelPageSize bytes, not
one byte.
Failure to calculate the offset correctly leads to corrupted unwind-info (and
consequently broken exceptions / unwinding) when more than one second level
page is needed. Since JITLink's unwind support only produces
UNWIND_SECOND_LEVEL_REGULAR-style pages this would trigger for any file
containing more than 511 functions with unwind info. The included test-case
contains 1022 functions (sufficient for both the current format and any
future implementation that supports UNWIND_SECOND_LEVEL_COMPRESSED pages).
Thanks to @edoardo on discord for spotting this bug!
(cherry picked from commit 88f55d16c4c247a9eef326961a1445dee3f2e30c)
---
.../Generic/exceptions-stress-test-tower.cpp | 1039 +++++++++++++++++
.../JITLink/CompactUnwindSupport.h | 5 +-
2 files changed, 1042 insertions(+), 2 deletions(-)
create mode 100644 compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
new file mode 100644
index 000000000000000..f7a39a9dccd6fcb
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
@@ -0,0 +1,1039 @@
+// RUN: %clangxx -c -o %t %s
+// RUN: %llvm_jitlink -slab-allocate=20Mb %t
+//
+// REQUIRES: system-darwin && host-arch-compatible
+
+// Test that we can throw and catch an exception through a large number of
+// stack frames. The number (1022) is chosen to force emission of multiple
+// unwind info second-level pages.
+
+static void f_0() { throw 42; }
+static void f_1() { try { f_0(); } catch (...) { throw; } }
+static void f_2() { try { f_1(); } catch (...) { throw; } }
+static void f_3() { try { f_2(); } catch (...) { throw; } }
+static void f_4() { try { f_3(); } catch (...) { throw; } }
+static void f_5() { try { f_4(); } catch (...) { throw; } }
+static void f_6() { try { f_5(); } catch (...) { throw; } }
+static void f_7() { try { f_6(); } catch (...) { throw; } }
+static void f_8() { try { f_7(); } catch (...) { throw; } }
+static void f_9() { try { f_8(); } catch (...) { throw; } }
+static void f_10() { try { f_9(); } catch (...) { throw; } }
+static void f_11() { try { f_10(); } catch (...) { throw; } }
+static void f_12() { try { f_11(); } catch (...) { throw; } }
+static void f_13() { try { f_12(); } catch (...) { throw; } }
+static void f_14() { try { f_13(); } catch (...) { throw; } }
+static void f_15() { try { f_14(); } catch (...) { throw; } }
+static void f_16() { try { f_15(); } catch (...) { throw; } }
+static void f_17() { try { f_16(); } catch (...) { throw; } }
+static void f_18() { try { f_17(); } catch (...) { throw; } }
+static void f_19() { try { f_18(); } catch (...) { throw; } }
+static void f_20() { try { f_19(); } catch (...) { throw; } }
+static void f_21() { try { f_20(); } catch (...) { throw; } }
+static void f_22() { try { f_21(); } catch (...) { throw; } }
+static void f_23() { try { f_22(); } catch (...) { throw; } }
+static void f_24() { try { f_23(); } catch (...) { throw; } }
+static void f_25() { try { f_24(); } catch (...) { throw; } }
+static void f_26() { try { f_25(); } catch (...) { throw; } }
+static void f_27() { try { f_26(); } catch (...) { throw; } }
+static void f_28() { try { f_27(); } catch (...) { throw; } }
+static void f_29() { try { f_28(); } catch (...) { throw; } }
+static void f_30() { try { f_29(); } catch (...) { throw; } }
+static void f_31() { try { f_30(); } catch (...) { throw; } }
+static void f_32() { try { f_31(); } catch (...) { throw; } }
+static void f_33() { try { f_32(); } catch (...) { throw; } }
+static void f_34() { try { f_33(); } catch (...) { throw; } }
+static void f_35() { try { f_34(); } catch (...) { throw; } }
+static void f_36() { try { f_35(); } catch (...) { throw; } }
+static void f_37() { try { f_36(); } catch (...) { throw; } }
+static void f_38() { try { f_37(); } catch (...) { throw; } }
+static void f_39() { try { f_38(); } catch (...) { throw; } }
+static void f_40() { try { f_39(); } catch (...) { throw; } }
+static void f_41() { try { f_40(); } catch (...) { throw; } }
+static void f_42() { try { f_41(); } catch (...) { throw; } }
+static void f_43() { try { f_42(); } catch (...) { throw; } }
+static void f_44() { try { f_43(); } catch (...) { throw; } }
+static void f_45() { try { f_44(); } catch (...) { throw; } }
+static void f_46() { try { f_45(); } catch (...) { throw; } }
+static void f_47() { try { f_46(); } catch (...) { throw; } }
+static void f_48() { try { f_47(); } catch (...) { throw; } }
+static void f_49() { try { f_48(); } catch (...) { throw; } }
+static void f_50() { try { f_49(); } catch (...) { throw; } }
+static void f_51() { try { f_50(); } catch (...) { throw; } }
+static void f_52() { try { f_51(); } catch (...) { throw; } }
+static void f_53() { try { f_52(); } catch (...) { throw; } }
+static void f_54() { try { f_53(); } catch (...) { throw; } }
+static void f_55() { try { f_54(); } catch (...) { throw; } }
+static void f_56() { try { f_55(); } catch (...) { throw; } }
+static void f_57() { try { f_56(); } catch (...) { throw; } }
+static void f_58() { try { f_57(); } catch (...) { throw; } }
+static void f_59() { try { f_58(); } catch (...) { throw; } }
+static void f_60() { try { f_59(); } catch (...) { throw; } }
+static void f_61() { try { f_60(); } catch (...) { throw; } }
+static void f_62() { try { f_61(); } catch (...) { throw; } }
+static void f_63() { try { f_62(); } catch (...) { throw; } }
+static void f_64() { try { f_63(); } catch (...) { throw; } }
+static void f_65() { try { f_64(); } catch (...) { throw; } }
+static void f_66() { try { f_65(); } catch (...) { throw; } }
+static void f_67() { try { f_66(); } catch (...) { throw; } }
+static void f_68() { try { f_67(); } catch (...) { throw; } }
+static void f_69() { try { f_68(); } catch (...) { throw; } }
+static void f_70() { try { f_69(); } catch (...) { throw; } }
+static void f_71() { try { f_70(); } catch (...) { throw; } }
+static void f_72() { try { f_71(); } catch (...) { throw; } }
+static void f_73() { try { f_72(); } catch (...) { throw; } }
+static void f_74() { try { f_73(); } catch (...) { throw; } }
+static void f_75() { try { f_74(); } catch (...) { throw; } }
+static void f_76() { try { f_75(); } catch (...) { throw; } }
+static void f_77() { try { f_76(); } catch (...) { throw; } }
+static void f_78() { try { f_77(); } catch (...) { throw; } }
+static void f_79() { try { f_78(); } catch (...) { throw; } }
+static void f_80() { try { f_79(); } catch (...) { throw; } }
+static void f_81() { try { f_80(); } catch (...) { throw; } }
+static void f_82() { try { f_81(); } catch (...) { throw; } }
+static void f_83() { try { f_82(); } catch (...) { throw; } }
+static void f_84() { try { f_83(); } catch (...) { throw; } }
+static void f_85() { try { f_84(); } catch (...) { throw; } }
+static void f_86() { try { f_85(); } catch (...) { throw; } }
+static void f_87() { try { f_86(); } catch (...) { throw; } }
+static void f_88() { try { f_87(); } catch (...) { throw; } }
+static void f_89() { try { f_88(); } catch (...) { throw; } }
+static void f_90() { try { f_89(); } catch (...) { throw; } }
+static void f_91() { try { f_90(); } catch (...) { throw; } }
+static void f_92() { try { f_91(); } catch (...) { throw; } }
+static void f_93() { try { f_92(); } catch (...) { throw; } }
+static void f_94() { try { f_93(); } catch (...) { throw; } }
+static void f_95() { try { f_94(); } catch (...) { throw; } }
+static void f_96() { try { f_95(); } catch (...) { throw; } }
+static void f_97() { try { f_96(); } catch (...) { throw; } }
+static void f_98() { try { f_97(); } catch (...) { throw; } }
+static void f_99() { try { f_98(); } catch (...) { throw; } }
+static void f_100() { try { f_99(); } catch (...) { throw; } }
+static void f_101() { try { f_100(); } catch (...) { throw; } }
+static void f_102() { try { f_101(); } catch (...) { throw; } }
+static void f_103() { try { f_102(); } catch (...) { throw; } }
+static void f_104() { try { f_103(); } catch (...) { throw; } }
+static void f_105() { try { f_104(); } catch (...) { throw; } }
+static void f_106() { try { f_105(); } catch (...) { throw; } }
+static void f_107() { try { f_106(); } catch (...) { throw; } }
+static void f_108() { try { f_107(); } catch (...) { throw; } }
+static void f_109() { try { f_108(); } catch (...) { throw; } }
+static void f_110() { try { f_109(); } catch (...) { throw; } }
+static void f_111() { try { f_110(); } catch (...) { throw; } }
+static void f_112() { try { f_111(); } catch (...) { throw; } }
+static void f_113() { try { f_112(); } catch (...) { throw; } }
+static void f_114() { try { f_113(); } catch (...) { throw; } }
+static void f_115() { try { f_114(); } catch (...) { throw; } }
+static void f_116() { try { f_115(); } catch (...) { throw; } }
+static void f_117() { try { f_116(); } catch (...) { throw; } }
+static void f_118() { try { f_117(); } catch (...) { throw; } }
+static void f_119() { try { f_118(); } catch (...) { throw; } }
+static void f_120() { try { f_119(); } catch (...) { throw; } }
+static void f_121() { try { f_120(); } catch (...) { throw; } }
+static void f_122() { try { f_121(); } catch (...) { throw; } }
+static void f_123() { try { f_122(); } catch (...) { throw; } }
+static void f_124() { try { f_123(); } catch (...) { throw; } }
+static void f_125() { try { f_124(); } catch (...) { throw; } }
+static void f_126() { try { f_125(); } catch (...) { throw; } }
+static void f_127() { try { f_126(); } catch (...) { throw; } }
+static void f_128() { try { f_127(); } catch (...) { throw; } }
+static void f_129() { try { f_128(); } catch (...) { throw; } }
+static void f_130() { try { f_129(); } catch (...) { throw; } }
+static void f_131() { try { f_130(); } catch (...) { throw; } }
+static void f_132() { try { f_131(); } catch (...) { throw; } }
+static void f_133() { try { f_132(); } catch (...) { throw; } }
+static void f_134() { try { f_133(); } catch (...) { throw; } }
+static void f_135() { try { f_134(); } catch (...) { throw; } }
+static void f_136() { try { f_135(); } catch (...) { throw; } }
+static void f_137() { try { f_136(); } catch (...) { throw; } }
+static void f_138() { try { f_137(); } catch (...) { throw; } }
+static void f_139() { try { f_138(); } catch (...) { throw; } }
+static void f_140() { try { f_139(); } catch (...) { throw; } }
+static void f_141() { try { f_140(); } catch (...) { throw; } }
+static void f_142() { try { f_141(); } catch (...) { throw; } }
+static void f_143() { try { f_142(); } catch (...) { throw; } }
+static void f_144() { try { f_143(); } catch (...) { throw; } }
+static void f_145() { try { f_144(); } catch (...) { throw; } }
+static void f_146() { try { f_145(); } catch (...) { throw; } }
+static void f_147() { try { f_146(); } catch (...) { throw; } }
+static void f_148() { try { f_147(); } catch (...) { throw; } }
+static void f_149() { try { f_148(); } catch (...) { throw; } }
+static void f_150() { try { f_149(); } catch (...) { throw; } }
+static void f_151() { try { f_150(); } catch (...) { throw; } }
+static void f_152() { try { f_151(); } catch (...) { throw; } }
+static void f_153() { try { f_152(); } catch (...) { throw; } }
+static void f_154() { try { f_153(); } catch (...) { throw; } }
+static void f_155() { try { f_154(); } catch (...) { throw; } }
+static void f_156() { try { f_155(); } catch (...) { throw; } }
+static void f_157() { try { f_156(); } catch (...) { throw; } }
+static void f_158() { try { f_157(); } catch (...) { throw; } }
+static void f_159() { try { f_158(); } catch (...) { throw; } }
+static void f_160() { try { f_159(); } catch (...) { throw; } }
+static void f_161() { try { f_160(); } catch (...) { throw; } }
+static void f_162() { try { f_161(); } catch (...) { throw; } }
+static void f_163() { try { f_162(); } catch (...) { throw; } }
+static void f_164() { try { f_163(); } catch (...) { throw; } }
+static void f_165() { try { f_164(); } catch (...) { throw; } }
+static void f_166() { try { f_165(); } catch (...) { throw; } }
+static void f_167() { try { f_166(); } catch (...) { throw; } }
+static void f_168() { try { f_167(); } catch (...) { throw; } }
+static void f_169() { try { f_168(); } catch (...) { throw; } }
+static void f_170() { try { f_169(); } catch (...) { throw; } }
+static void f_171() { try { f_170(); } catch (...) { throw; } }
+static void f_172() { try { f_171(); } catch (...) { throw; } }
+static void f_173() { try { f_172(); } catch (...) { throw; } }
+static void f_174() { try { f_173(); } catch (...) { throw; } }
+static void f_175() { try { f_174(); } catch (...) { throw; } }
+static void f_176() { try { f_175(); } catch (...) { throw; } }
+static void f_177() { try { f_176(); } catch (...) { throw; } }
+static void f_178() { try { f_177(); } catch (...) { throw; } }
+static void f_179() { try { f_178(); } catch (...) { throw; } }
+static void f_180() { try { f_179(); } catch (...) { throw; } }
+static void f_181() { try { f_180(); } catch (...) { throw; } }
+static void f_182() { try { f_181(); } catch (...) { throw; } }
+static void f_183() { try { f_182(); } catch (...) { throw; } }
+static void f_184() { try { f_183(); } catch (...) { throw; } }
+static void f_185() { try { f_184(); } catch (...) { throw; } }
+static void f_186() { try { f_185(); } catch (...) { throw; } }
+static void f_187() { try { f_186(); } catch (...) { throw; } }
+static void f_188() { try { f_187(); } catch (...) { throw; } }
+static void f_189() { try { f_188(); } catch (...) { throw; } }
+static void f_190() { try { f_189(); } catch (...) { throw; } }
+static void f_191() { try { f_190(); } catch (...) { throw; } }
+static void f_192() { try { f_191(); } catch (...) { throw; } }
+static void f_193() { try { f_192(); } catch (...) { throw; } }
+static void f_194() { try { f_193(); } catch (...) { throw; } }
+static void f_195() { try { f_194(); } catch (...) { throw; } }
+static void f_196() { try { f_195(); } catch (...) { throw; } }
+static void f_197() { try { f_196(); } catch (...) { throw; } }
+static void f_198() { try { f_197(); } catch (...) { throw; } }
+static void f_199() { try { f_198(); } catch (...) { throw; } }
+static void f_200() { try { f_199(); } catch (...) { throw; } }
+static void f_201() { try { f_200(); } catch (...) { throw; } }
+static void f_202() { try { f_201(); } catch (...) { throw; } }
+static void f_203() { try { f_202(); } catch (...) { throw; } }
+static void f_204() { try { f_203(); } catch (...) { throw; } }
+static void f_205() { try { f_204(); } catch (...) { throw; } }
+static void f_206() { try { f_205(); } catch (...) { throw; } }
+static void f_207() { try { f_206(); } catch (...) { throw; } }
+static void f_208() { try { f_207(); } catch (...) { throw; } }
+static void f_209() { try { f_208(); } catch (...) { throw; } }
+static void f_210() { try { f_209(); } catch (...) { throw; } }
+static void f_211() { try { f_210(); } catch (...) { throw; } }
+static void f_212() { try { f_211(); } catch (...) { throw; } }
+static void f_213() { try { f_212(); } catch (...) { throw; } }
+static void f_214() { try { f_213(); } catch (...) { throw; } }
+static void f_215() { try { f_214(); } catch (...) { throw; } }
+static void f_216() { try { f_215(); } catch (...) { throw; } }
+static void f_217() { try { f_216(); } catch (...) { throw; } }
+static void f_218() { try { f_217(); } catch (...) { throw; } }
+static void f_219() { try { f_218(); } catch (...) { throw; } }
+static void f_220() { try { f_219(); } catch (...) { throw; } }
+static void f_221() { try { f_220(); } catch (...) { throw; } }
+static void f_222() { try { f_221(); } catch (...) { throw; } }
+static void f_223() { try { f_222(); } catch (...) { throw; } }
+static void f_224() { try { f_223(); } catch (...) { throw; } }
+static void f_225() { try { f_224(); } catch (...) { throw; } }
+static void f_226() { try { f_225(); } catch (...) { throw; } }
+static void f_227() { try { f_226(); } catch (...) { throw; } }
+static void f_228() { try { f_227(); } catch (...) { throw; } }
+static void f_229() { try { f_228(); } catch (...) { throw; } }
+static void f_230() { try { f_229(); } catch (...) { throw; } }
+static void f_231() { try { f_230(); } catch (...) { throw; } }
+static void f_232() { try { f_231(); } catch (...) { throw; } }
+static void f_233() { try { f_232(); } catch (...) { throw; } }
+static void f_234() { try { f_233(); } catch (...) { throw; } }
+static void f_235() { try { f_234(); } catch (...) { throw; } }
+static void f_236() { try { f_235(); } catch (...) { throw; } }
+static void f_237() { try { f_236(); } catch (...) { throw; } }
+static void f_238() { try { f_237(); } catch (...) { throw; } }
+static void f_239() { try { f_238(); } catch (...) { throw; } }
+static void f_240() { try { f_239(); } catch (...) { throw; } }
+static void f_241() { try { f_240(); } catch (...) { throw; } }
+static void f_242() { try { f_241(); } catch (...) { throw; } }
+static void f_243() { try { f_242(); } catch (...) { throw; } }
+static void f_244() { try { f_243(); } catch (...) { throw; } }
+static void f_245() { try { f_244(); } catch (...) { throw; } }
+static void f_246() { try { f_245(); } catch (...) { throw; } }
+static void f_247() { try { f_246(); } catch (...) { throw; } }
+static void f_248() { try { f_247(); } catch (...) { throw; } }
+static void f_249() { try { f_248(); } catch (...) { throw; } }
+static void f_250() { try { f_249(); } catch (...) { throw; } }
+static void f_251() { try { f_250(); } catch (...) { throw; } }
+static void f_252() { try { f_251(); } catch (...) { throw; } }
+static void f_253() { try { f_252(); } catch (...) { throw; } }
+static void f_254() { try { f_253(); } catch (...) { throw; } }
+static void f_255() { try { f_254(); } catch (...) { throw; } }
+static void f_256() { try { f_255(); } catch (...) { throw; } }
+static void f_257() { try { f_256(); } catch (...) { throw; } }
+static void f_258() { try { f_257(); } catch (...) { throw; } }
+static void f_259() { try { f_258(); } catch (...) { throw; } }
+static void f_260() { try { f_259(); } catch (...) { throw; } }
+static void f_261() { try { f_260(); } catch (...) { throw; } }
+static void f_262() { try { f_261(); } catch (...) { throw; } }
+static void f_263() { try { f_262(); } catch (...) { throw; } }
+static void f_264() { try { f_263(); } catch (...) { throw; } }
+static void f_265() { try { f_264(); } catch (...) { throw; } }
+static void f_266() { try { f_265(); } catch (...) { throw; } }
+static void f_267() { try { f_266(); } catch (...) { throw; } }
+static void f_268() { try { f_267(); } catch (...) { throw; } }
+static void f_269() { try { f_268(); } catch (...) { throw; } }
+static void f_270() { try { f_269(); } catch (...) { throw; } }
+static void f_271() { try { f_270(); } catch (...) { throw; } }
+static void f_272() { try { f_271(); } catch (...) { throw; } }
+static void f_273() { try { f_272(); } catch (...) { throw; } }
+static void f_274() { try { f_273(); } catch (...) { throw; } }
+static void f_275() { try { f_274(); } catch (...) { throw; } }
+static void f_276() { try { f_275(); } catch (...) { throw; } }
+static void f_277() { try { f_276(); } catch (...) { throw; } }
+static void f_278() { try { f_277(); } catch (...) { throw; } }
+static void f_279() { try { f_278(); } catch (...) { throw; } }
+static void f_280() { try { f_279(); } catch (...) { throw; } }
+static void f_281() { try { f_280(); } catch (...) { throw; } }
+static void f_282() { try { f_281(); } catch (...) { throw; } }
+static void f_283() { try { f_282(); } catch (...) { throw; } }
+static void f_284() { try { f_283(); } catch (...) { throw; } }
+static void f_285() { try { f_284(); } catch (...) { throw; } }
+static void f_286() { try { f_285(); } catch (...) { throw; } }
+static void f_287() { try { f_286(); } catch (...) { throw; } }
+static void f_288() { try { f_287(); } catch (...) { throw; } }
+static void f_289() { try { f_288(); } catch (...) { throw; } }
+static void f_290() { try { f_289(); } catch (...) { throw; } }
+static void f_291() { try { f_290(); } catch (...) { throw; } }
+static void f_292() { try { f_291(); } catch (...) { throw; } }
+static void f_293() { try { f_292(); } catch (...) { throw; } }
+static void f_294() { try { f_293(); } catch (...) { throw; } }
+static void f_295() { try { f_294(); } catch (...) { throw; } }
+static void f_296() { try { f_295(); } catch (...) { throw; } }
+static void f_297() { try { f_296(); } catch (...) { throw; } }
+static void f_298() { try { f_297(); } catch (...) { throw; } }
+static void f_299() { try { f_298(); } catch (...) { throw; } }
+static void f_300() { try { f_299(); } catch (...) { throw; } }
+static void f_301() { try { f_300(); } catch (...) { throw; } }
+static void f_302() { try { f_301(); } catch (...) { throw; } }
+static void f_303() { try { f_302(); } catch (...) { throw; } }
+static void f_304() { try { f_303(); } catch (...) { throw; } }
+static void f_305() { try { f_304(); } catch (...) { throw; } }
+static void f_306() { try { f_305(); } catch (...) { throw; } }
+static void f_307() { try { f_306(); } catch (...) { throw; } }
+static void f_308() { try { f_307(); } catch (...) { throw; } }
+static void f_309() { try { f_308(); } catch (...) { throw; } }
+static void f_310() { try { f_309(); } catch (...) { throw; } }
+static void f_311() { try { f_310(); } catch (...) { throw; } }
+static void f_312() { try { f_311(); } catch (...) { throw; } }
+static void f_313() { try { f_312(); } catch (...) { throw; } }
+static void f_314() { try { f_313(); } catch (...) { throw; } }
+static void f_315() { try { f_314(); } catch (...) { throw; } }
+static void f_316() { try { f_315(); } catch (...) { throw; } }
+static void f_317() { try { f_316(); } catch (...) { throw; } }
+static void f_318() { try { f_317(); } catch (...) { throw; } }
+static void f_319() { try { f_318(); } catch (...) { throw; } }
+static void f_320() { try { f_319(); } catch (...) { throw; } }
+static void f_321() { try { f_320(); } catch (...) { throw; } }
+static void f_322() { try { f_321(); } catch (...) { throw; } }
+static void f_323() { try { f_322(); } catch (...) { throw; } }
+static void f_324() { try { f_323(); } catch (...) { throw; } }
+static void f_325() { try { f_324(); } catch (...) { throw; } }
+static void f_326() { try { f_325(); } catch (...) { throw; } }
+static void f_327() { try { f_326(); } catch (...) { throw; } }
+static void f_328() { try { f_327(); } catch (...) { throw; } }
+static void f_329() { try { f_328(); } catch (...) { throw; } }
+static void f_330() { try { f_329(); } catch (...) { throw; } }
+static void f_331() { try { f_330(); } catch (...) { throw; } }
+static void f_332() { try { f_331(); } catch (...) { throw; } }
+static void f_333() { try { f_332(); } catch (...) { throw; } }
+static void f_334() { try { f_333(); } catch (...) { throw; } }
+static void f_335() { try { f_334(); } catch (...) { throw; } }
+static void f_336() { try { f_335(); } catch (...) { throw; } }
+static void f_337() { try { f_336(); } catch (...) { throw; } }
+static void f_338() { try { f_337(); } catch (...) { throw; } }
+static void f_339() { try { f_338(); } catch (...) { throw; } }
+static void f_340() { try { f_339(); } catch (...) { throw; } }
+static void f_341() { try { f_340(); } catch (...) { throw; } }
+static void f_342() { try { f_341(); } catch (...) { throw; } }
+static void f_343() { try { f_342(); } catch (...) { throw; } }
+static void f_344() { try { f_343(); } catch (...) { throw; } }
+static void f_345() { try { f_344(); } catch (...) { throw; } }
+static void f_346() { try { f_345(); } catch (...) { throw; } }
+static void f_347() { try { f_346(); } catch (...) { throw; } }
+static void f_348() { try { f_347(); } catch (...) { throw; } }
+static void f_349() { try { f_348(); } catch (...) { throw; } }
+static void f_350() { try { f_349(); } catch (...) { throw; } }
+static void f_351() { try { f_350(); } catch (...) { throw; } }
+static void f_352() { try { f_351(); } catch (...) { throw; } }
+static void f_353() { try { f_352(); } catch (...) { throw; } }
+static void f_354() { try { f_353(); } catch (...) { throw; } }
+static void f_355() { try { f_354(); } catch (...) { throw; } }
+static void f_356() { try { f_355(); } catch (...) { throw; } }
+static void f_357() { try { f_356(); } catch (...) { throw; } }
+static void f_358() { try { f_357(); } catch (...) { throw; } }
+static void f_359() { try { f_358(); } catch (...) { throw; } }
+static void f_360() { try { f_359(); } catch (...) { throw; } }
+static void f_361() { try { f_360(); } catch (...) { throw; } }
+static void f_362() { try { f_361(); } catch (...) { throw; } }
+static void f_363() { try { f_362(); } catch (...) { throw; } }
+static void f_364() { try { f_363(); } catch (...) { throw; } }
+static void f_365() { try { f_364(); } catch (...) { throw; } }
+static void f_366() { try { f_365(); } catch (...) { throw; } }
+static void f_367() { try { f_366(); } catch (...) { throw; } }
+static void f_368() { try { f_367(); } catch (...) { throw; } }
+static void f_369() { try { f_368(); } catch (...) { throw; } }
+static void f_370() { try { f_369(); } catch (...) { throw; } }
+static void f_371() { try { f_370(); } catch (...) { throw; } }
+static void f_372() { try { f_371(); } catch (...) { throw; } }
+static void f_373() { try { f_372(); } catch (...) { throw; } }
+static void f_374() { try { f_373(); } catch (...) { throw; } }
+static void f_375() { try { f_374(); } catch (...) { throw; } }
+static void f_376() { try { f_375(); } catch (...) { throw; } }
+static void f_377() { try { f_376(); } catch (...) { throw; } }
+static void f_378() { try { f_377(); } catch (...) { throw; } }
+static void f_379() { try { f_378(); } catch (...) { throw; } }
+static void f_380() { try { f_379(); } catch (...) { throw; } }
+static void f_381() { try { f_380(); } catch (...) { throw; } }
+static void f_382() { try { f_381(); } catch (...) { throw; } }
+static void f_383() { try { f_382(); } catch (...) { throw; } }
+static void f_384() { try { f_383(); } catch (...) { throw; } }
+static void f_385() { try { f_384(); } catch (...) { throw; } }
+static void f_386() { try { f_385(); } catch (...) { throw; } }
+static void f_387() { try { f_386(); } catch (...) { throw; } }
+static void f_388() { try { f_387(); } catch (...) { throw; } }
+static void f_389() { try { f_388(); } catch (...) { throw; } }
+static void f_390() { try { f_389(); } catch (...) { throw; } }
+static void f_391() { try { f_390(); } catch (...) { throw; } }
+static void f_392() { try { f_391(); } catch (...) { throw; } }
+static void f_393() { try { f_392(); } catch (...) { throw; } }
+static void f_394() { try { f_393(); } catch (...) { throw; } }
+static void f_395() { try { f_394(); } catch (...) { throw; } }
+static void f_396() { try { f_395(); } catch (...) { throw; } }
+static void f_397() { try { f_396(); } catch (...) { throw; } }
+static void f_398() { try { f_397(); } catch (...) { throw; } }
+static void f_399() { try { f_398(); } catch (...) { throw; } }
+static void f_400() { try { f_399(); } catch (...) { throw; } }
+static void f_401() { try { f_400(); } catch (...) { throw; } }
+static void f_402() { try { f_401(); } catch (...) { throw; } }
+static void f_403() { try { f_402(); } catch (...) { throw; } }
+static void f_404() { try { f_403(); } catch (...) { throw; } }
+static void f_405() { try { f_404(); } catch (...) { throw; } }
+static void f_406() { try { f_405(); } catch (...) { throw; } }
+static void f_407() { try { f_406(); } catch (...) { throw; } }
+static void f_408() { try { f_407(); } catch (...) { throw; } }
+static void f_409() { try { f_408(); } catch (...) { throw; } }
+static void f_410() { try { f_409(); } catch (...) { throw; } }
+static void f_411() { try { f_410(); } catch (...) { throw; } }
+static void f_412() { try { f_411(); } catch (...) { throw; } }
+static void f_413() { try { f_412(); } catch (...) { throw; } }
+static void f_414() { try { f_413(); } catch (...) { throw; } }
+static void f_415() { try { f_414(); } catch (...) { throw; } }
+static void f_416() { try { f_415(); } catch (...) { throw; } }
+static void f_417() { try { f_416(); } catch (...) { throw; } }
+static void f_418() { try { f_417(); } catch (...) { throw; } }
+static void f_419() { try { f_418(); } catch (...) { throw; } }
+static void f_420() { try { f_419(); } catch (...) { throw; } }
+static void f_421() { try { f_420(); } catch (...) { throw; } }
+static void f_422() { try { f_421(); } catch (...) { throw; } }
+static void f_423() { try { f_422(); } catch (...) { throw; } }
+static void f_424() { try { f_423(); } catch (...) { throw; } }
+static void f_425() { try { f_424(); } catch (...) { throw; } }
+static void f_426() { try { f_425(); } catch (...) { throw; } }
+static void f_427() { try { f_426(); } catch (...) { throw; } }
+static void f_428() { try { f_427(); } catch (...) { throw; } }
+static void f_429() { try { f_428(); } catch (...) { throw; } }
+static void f_430() { try { f_429(); } catch (...) { throw; } }
+static void f_431() { try { f_430(); } catch (...) { throw; } }
+static void f_432() { try { f_431(); } catch (...) { throw; } }
+static void f_433() { try { f_432(); } catch (...) { throw; } }
+static void f_434() { try { f_433(); } catch (...) { throw; } }
+static void f_435() { try { f_434(); } catch (...) { throw; } }
+static void f_436() { try { f_435(); } catch (...) { throw; } }
+static void f_437() { try { f_436(); } catch (...) { throw; } }
+static void f_438() { try { f_437(); } catch (...) { throw; } }
+static void f_439() { try { f_438(); } catch (...) { throw; } }
+static void f_440() { try { f_439(); } catch (...) { throw; } }
+static void f_441() { try { f_440(); } catch (...) { throw; } }
+static void f_442() { try { f_441(); } catch (...) { throw; } }
+static void f_443() { try { f_442(); } catch (...) { throw; } }
+static void f_444() { try { f_443(); } catch (...) { throw; } }
+static void f_445() { try { f_444(); } catch (...) { throw; } }
+static void f_446() { try { f_445(); } catch (...) { throw; } }
+static void f_447() { try { f_446(); } catch (...) { throw; } }
+static void f_448() { try { f_447(); } catch (...) { throw; } }
+static void f_449() { try { f_448(); } catch (...) { throw; } }
+static void f_450() { try { f_449(); } catch (...) { throw; } }
+static void f_451() { try { f_450(); } catch (...) { throw; } }
+static void f_452() { try { f_451(); } catch (...) { throw; } }
+static void f_453() { try { f_452(); } catch (...) { throw; } }
+static void f_454() { try { f_453(); } catch (...) { throw; } }
+static void f_455() { try { f_454(); } catch (...) { throw; } }
+static void f_456() { try { f_455(); } catch (...) { throw; } }
+static void f_457() { try { f_456(); } catch (...) { throw; } }
+static void f_458() { try { f_457(); } catch (...) { throw; } }
+static void f_459() { try { f_458(); } catch (...) { throw; } }
+static void f_460() { try { f_459(); } catch (...) { throw; } }
+static void f_461() { try { f_460(); } catch (...) { throw; } }
+static void f_462() { try { f_461(); } catch (...) { throw; } }
+static void f_463() { try { f_462(); } catch (...) { throw; } }
+static void f_464() { try { f_463(); } catch (...) { throw; } }
+static void f_465() { try { f_464(); } catch (...) { throw; } }
+static void f_466() { try { f_465(); } catch (...) { throw; } }
+static void f_467() { try { f_466(); } catch (...) { throw; } }
+static void f_468() { try { f_467(); } catch (...) { throw; } }
+static void f_469() { try { f_468(); } catch (...) { throw; } }
+static void f_470() { try { f_469(); } catch (...) { throw; } }
+static void f_471() { try { f_470(); } catch (...) { throw; } }
+static void f_472() { try { f_471(); } catch (...) { throw; } }
+static void f_473() { try { f_472(); } catch (...) { throw; } }
+static void f_474() { try { f_473(); } catch (...) { throw; } }
+static void f_475() { try { f_474(); } catch (...) { throw; } }
+static void f_476() { try { f_475(); } catch (...) { throw; } }
+static void f_477() { try { f_476(); } catch (...) { throw; } }
+static void f_478() { try { f_477(); } catch (...) { throw; } }
+static void f_479() { try { f_478(); } catch (...) { throw; } }
+static void f_480() { try { f_479(); } catch (...) { throw; } }
+static void f_481() { try { f_480(); } catch (...) { throw; } }
+static void f_482() { try { f_481(); } catch (...) { throw; } }
+static void f_483() { try { f_482(); } catch (...) { throw; } }
+static void f_484() { try { f_483(); } catch (...) { throw; } }
+static void f_485() { try { f_484(); } catch (...) { throw; } }
+static void f_486() { try { f_485(); } catch (...) { throw; } }
+static void f_487() { try { f_486(); } catch (...) { throw; } }
+static void f_488() { try { f_487(); } catch (...) { throw; } }
+static void f_489() { try { f_488(); } catch (...) { throw; } }
+static void f_490() { try { f_489(); } catch (...) { throw; } }
+static void f_491() { try { f_490(); } catch (...) { throw; } }
+static void f_492() { try { f_491(); } catch (...) { throw; } }
+static void f_493() { try { f_492(); } catch (...) { throw; } }
+static void f_494() { try { f_493(); } catch (...) { throw; } }
+static void f_495() { try { f_494(); } catch (...) { throw; } }
+static void f_496() { try { f_495(); } catch (...) { throw; } }
+static void f_497() { try { f_496(); } catch (...) { throw; } }
+static void f_498() { try { f_497(); } catch (...) { throw; } }
+static void f_499() { try { f_498(); } catch (...) { throw; } }
+static void f_500() { try { f_499(); } catch (...) { throw; } }
+static void f_501() { try { f_500(); } catch (...) { throw; } }
+static void f_502() { try { f_501(); } catch (...) { throw; } }
+static void f_503() { try { f_502(); } catch (...) { throw; } }
+static void f_504() { try { f_503(); } catch (...) { throw; } }
+static void f_505() { try { f_504(); } catch (...) { throw; } }
+static void f_506() { try { f_505(); } catch (...) { throw; } }
+static void f_507() { try { f_506(); } catch (...) { throw; } }
+static void f_508() { try { f_507(); } catch (...) { throw; } }
+static void f_509() { try { f_508(); } catch (...) { throw; } }
+static void f_510() { try { f_509(); } catch (...) { throw; } }
+static void f_511() { try { f_510(); } catch (...) { throw; } }
+static void f_512() { try { f_511(); } catch (...) { throw; } }
+static void f_513() { try { f_512(); } catch (...) { throw; } }
+static void f_514() { try { f_513(); } catch (...) { throw; } }
+static void f_515() { try { f_514(); } catch (...) { throw; } }
+static void f_516() { try { f_515(); } catch (...) { throw; } }
+static void f_517() { try { f_516(); } catch (...) { throw; } }
+static void f_518() { try { f_517(); } catch (...) { throw; } }
+static void f_519() { try { f_518(); } catch (...) { throw; } }
+static void f_520() { try { f_519(); } catch (...) { throw; } }
+static void f_521() { try { f_520(); } catch (...) { throw; } }
+static void f_522() { try { f_521(); } catch (...) { throw; } }
+static void f_523() { try { f_522(); } catch (...) { throw; } }
+static void f_524() { try { f_523(); } catch (...) { throw; } }
+static void f_525() { try { f_524(); } catch (...) { throw; } }
+static void f_526() { try { f_525(); } catch (...) { throw; } }
+static void f_527() { try { f_526(); } catch (...) { throw; } }
+static void f_528() { try { f_527(); } catch (...) { throw; } }
+static void f_529() { try { f_528(); } catch (...) { throw; } }
+static void f_530() { try { f_529(); } catch (...) { throw; } }
+static void f_531() { try { f_530(); } catch (...) { throw; } }
+static void f_532() { try { f_531(); } catch (...) { throw; } }
+static void f_533() { try { f_532(); } catch (...) { throw; } }
+static void f_534() { try { f_533(); } catch (...) { throw; } }
+static void f_535() { try { f_534(); } catch (...) { throw; } }
+static void f_536() { try { f_535(); } catch (...) { throw; } }
+static void f_537() { try { f_536(); } catch (...) { throw; } }
+static void f_538() { try { f_537(); } catch (...) { throw; } }
+static void f_539() { try { f_538(); } catch (...) { throw; } }
+static void f_540() { try { f_539(); } catch (...) { throw; } }
+static void f_541() { try { f_540(); } catch (...) { throw; } }
+static void f_542() { try { f_541(); } catch (...) { throw; } }
+static void f_543() { try { f_542(); } catch (...) { throw; } }
+static void f_544() { try { f_543(); } catch (...) { throw; } }
+static void f_545() { try { f_544(); } catch (...) { throw; } }
+static void f_546() { try { f_545(); } catch (...) { throw; } }
+static void f_547() { try { f_546(); } catch (...) { throw; } }
+static void f_548() { try { f_547(); } catch (...) { throw; } }
+static void f_549() { try { f_548(); } catch (...) { throw; } }
+static void f_550() { try { f_549(); } catch (...) { throw; } }
+static void f_551() { try { f_550(); } catch (...) { throw; } }
+static void f_552() { try { f_551(); } catch (...) { throw; } }
+static void f_553() { try { f_552(); } catch (...) { throw; } }
+static void f_554() { try { f_553(); } catch (...) { throw; } }
+static void f_555() { try { f_554(); } catch (...) { throw; } }
+static void f_556() { try { f_555(); } catch (...) { throw; } }
+static void f_557() { try { f_556(); } catch (...) { throw; } }
+static void f_558() { try { f_557(); } catch (...) { throw; } }
+static void f_559() { try { f_558(); } catch (...) { throw; } }
+static void f_560() { try { f_559(); } catch (...) { throw; } }
+static void f_561() { try { f_560(); } catch (...) { throw; } }
+static void f_562() { try { f_561(); } catch (...) { throw; } }
+static void f_563() { try { f_562(); } catch (...) { throw; } }
+static void f_564() { try { f_563(); } catch (...) { throw; } }
+static void f_565() { try { f_564(); } catch (...) { throw; } }
+static void f_566() { try { f_565(); } catch (...) { throw; } }
+static void f_567() { try { f_566(); } catch (...) { throw; } }
+static void f_568() { try { f_567(); } catch (...) { throw; } }
+static void f_569() { try { f_568(); } catch (...) { throw; } }
+static void f_570() { try { f_569(); } catch (...) { throw; } }
+static void f_571() { try { f_570(); } catch (...) { throw; } }
+static void f_572() { try { f_571(); } catch (...) { throw; } }
+static void f_573() { try { f_572(); } catch (...) { throw; } }
+static void f_574() { try { f_573(); } catch (...) { throw; } }
+static void f_575() { try { f_574(); } catch (...) { throw; } }
+static void f_576() { try { f_575(); } catch (...) { throw; } }
+static void f_577() { try { f_576(); } catch (...) { throw; } }
+static void f_578() { try { f_577(); } catch (...) { throw; } }
+static void f_579() { try { f_578(); } catch (...) { throw; } }
+static void f_580() { try { f_579(); } catch (...) { throw; } }
+static void f_581() { try { f_580(); } catch (...) { throw; } }
+static void f_582() { try { f_581(); } catch (...) { throw; } }
+static void f_583() { try { f_582(); } catch (...) { throw; } }
+static void f_584() { try { f_583(); } catch (...) { throw; } }
+static void f_585() { try { f_584(); } catch (...) { throw; } }
+static void f_586() { try { f_585(); } catch (...) { throw; } }
+static void f_587() { try { f_586(); } catch (...) { throw; } }
+static void f_588() { try { f_587(); } catch (...) { throw; } }
+static void f_589() { try { f_588(); } catch (...) { throw; } }
+static void f_590() { try { f_589(); } catch (...) { throw; } }
+static void f_591() { try { f_590(); } catch (...) { throw; } }
+static void f_592() { try { f_591(); } catch (...) { throw; } }
+static void f_593() { try { f_592(); } catch (...) { throw; } }
+static void f_594() { try { f_593(); } catch (...) { throw; } }
+static void f_595() { try { f_594(); } catch (...) { throw; } }
+static void f_596() { try { f_595(); } catch (...) { throw; } }
+static void f_597() { try { f_596(); } catch (...) { throw; } }
+static void f_598() { try { f_597(); } catch (...) { throw; } }
+static void f_599() { try { f_598(); } catch (...) { throw; } }
+static void f_600() { try { f_599(); } catch (...) { throw; } }
+static void f_601() { try { f_600(); } catch (...) { throw; } }
+static void f_602() { try { f_601(); } catch (...) { throw; } }
+static void f_603() { try { f_602(); } catch (...) { throw; } }
+static void f_604() { try { f_603(); } catch (...) { throw; } }
+static void f_605() { try { f_604(); } catch (...) { throw; } }
+static void f_606() { try { f_605(); } catch (...) { throw; } }
+static void f_607() { try { f_606(); } catch (...) { throw; } }
+static void f_608() { try { f_607(); } catch (...) { throw; } }
+static void f_609() { try { f_608(); } catch (...) { throw; } }
+static void f_610() { try { f_609(); } catch (...) { throw; } }
+static void f_611() { try { f_610(); } catch (...) { throw; } }
+static void f_612() { try { f_611(); } catch (...) { throw; } }
+static void f_613() { try { f_612(); } catch (...) { throw; } }
+static void f_614() { try { f_613(); } catch (...) { throw; } }
+static void f_615() { try { f_614(); } catch (...) { throw; } }
+static void f_616() { try { f_615(); } catch (...) { throw; } }
+static void f_617() { try { f_616(); } catch (...) { throw; } }
+static void f_618() { try { f_617(); } catch (...) { throw; } }
+static void f_619() { try { f_618(); } catch (...) { throw; } }
+static void f_620() { try { f_619(); } catch (...) { throw; } }
+static void f_621() { try { f_620(); } catch (...) { throw; } }
+static void f_622() { try { f_621(); } catch (...) { throw; } }
+static void f_623() { try { f_622(); } catch (...) { throw; } }
+static void f_624() { try { f_623(); } catch (...) { throw; } }
+static void f_625() { try { f_624(); } catch (...) { throw; } }
+static void f_626() { try { f_625(); } catch (...) { throw; } }
+static void f_627() { try { f_626(); } catch (...) { throw; } }
+static void f_628() { try { f_627(); } catch (...) { throw; } }
+static void f_629() { try { f_628(); } catch (...) { throw; } }
+static void f_630() { try { f_629(); } catch (...) { throw; } }
+static void f_631() { try { f_630(); } catch (...) { throw; } }
+static void f_632() { try { f_631(); } catch (...) { throw; } }
+static void f_633() { try { f_632(); } catch (...) { throw; } }
+static void f_634() { try { f_633(); } catch (...) { throw; } }
+static void f_635() { try { f_634(); } catch (...) { throw; } }
+static void f_636() { try { f_635(); } catch (...) { throw; } }
+static void f_637() { try { f_636(); } catch (...) { throw; } }
+static void f_638() { try { f_637(); } catch (...) { throw; } }
+static void f_639() { try { f_638(); } catch (...) { throw; } }
+static void f_640() { try { f_639(); } catch (...) { throw; } }
+static void f_641() { try { f_640(); } catch (...) { throw; } }
+static void f_642() { try { f_641(); } catch (...) { throw; } }
+static void f_643() { try { f_642(); } catch (...) { throw; } }
+static void f_644() { try { f_643(); } catch (...) { throw; } }
+static void f_645() { try { f_644(); } catch (...) { throw; } }
+static void f_646() { try { f_645(); } catch (...) { throw; } }
+static void f_647() { try { f_646(); } catch (...) { throw; } }
+static void f_648() { try { f_647(); } catch (...) { throw; } }
+static void f_649() { try { f_648(); } catch (...) { throw; } }
+static void f_650() { try { f_649(); } catch (...) { throw; } }
+static void f_651() { try { f_650(); } catch (...) { throw; } }
+static void f_652() { try { f_651(); } catch (...) { throw; } }
+static void f_653() { try { f_652(); } catch (...) { throw; } }
+static void f_654() { try { f_653(); } catch (...) { throw; } }
+static void f_655() { try { f_654(); } catch (...) { throw; } }
+static void f_656() { try { f_655(); } catch (...) { throw; } }
+static void f_657() { try { f_656(); } catch (...) { throw; } }
+static void f_658() { try { f_657(); } catch (...) { throw; } }
+static void f_659() { try { f_658(); } catch (...) { throw; } }
+static void f_660() { try { f_659(); } catch (...) { throw; } }
+static void f_661() { try { f_660(); } catch (...) { throw; } }
+static void f_662() { try { f_661(); } catch (...) { throw; } }
+static void f_663() { try { f_662(); } catch (...) { throw; } }
+static void f_664() { try { f_663(); } catch (...) { throw; } }
+static void f_665() { try { f_664(); } catch (...) { throw; } }
+static void f_666() { try { f_665(); } catch (...) { throw; } }
+static void f_667() { try { f_666(); } catch (...) { throw; } }
+static void f_668() { try { f_667(); } catch (...) { throw; } }
+static void f_669() { try { f_668(); } catch (...) { throw; } }
+static void f_670() { try { f_669(); } catch (...) { throw; } }
+static void f_671() { try { f_670(); } catch (...) { throw; } }
+static void f_672() { try { f_671(); } catch (...) { throw; } }
+static void f_673() { try { f_672(); } catch (...) { throw; } }
+static void f_674() { try { f_673(); } catch (...) { throw; } }
+static void f_675() { try { f_674(); } catch (...) { throw; } }
+static void f_676() { try { f_675(); } catch (...) { throw; } }
+static void f_677() { try { f_676(); } catch (...) { throw; } }
+static void f_678() { try { f_677(); } catch (...) { throw; } }
+static void f_679() { try { f_678(); } catch (...) { throw; } }
+static void f_680() { try { f_679(); } catch (...) { throw; } }
+static void f_681() { try { f_680(); } catch (...) { throw; } }
+static void f_682() { try { f_681(); } catch (...) { throw; } }
+static void f_683() { try { f_682(); } catch (...) { throw; } }
+static void f_684() { try { f_683(); } catch (...) { throw; } }
+static void f_685() { try { f_684(); } catch (...) { throw; } }
+static void f_686() { try { f_685(); } catch (...) { throw; } }
+static void f_687() { try { f_686(); } catch (...) { throw; } }
+static void f_688() { try { f_687(); } catch (...) { throw; } }
+static void f_689() { try { f_688(); } catch (...) { throw; } }
+static void f_690() { try { f_689(); } catch (...) { throw; } }
+static void f_691() { try { f_690(); } catch (...) { throw; } }
+static void f_692() { try { f_691(); } catch (...) { throw; } }
+static void f_693() { try { f_692(); } catch (...) { throw; } }
+static void f_694() { try { f_693(); } catch (...) { throw; } }
+static void f_695() { try { f_694(); } catch (...) { throw; } }
+static void f_696() { try { f_695(); } catch (...) { throw; } }
+static void f_697() { try { f_696(); } catch (...) { throw; } }
+static void f_698() { try { f_697(); } catch (...) { throw; } }
+static void f_699() { try { f_698(); } catch (...) { throw; } }
+static void f_700() { try { f_699(); } catch (...) { throw; } }
+static void f_701() { try { f_700(); } catch (...) { throw; } }
+static void f_702() { try { f_701(); } catch (...) { throw; } }
+static void f_703() { try { f_702(); } catch (...) { throw; } }
+static void f_704() { try { f_703(); } catch (...) { throw; } }
+static void f_705() { try { f_704(); } catch (...) { throw; } }
+static void f_706() { try { f_705(); } catch (...) { throw; } }
+static void f_707() { try { f_706(); } catch (...) { throw; } }
+static void f_708() { try { f_707(); } catch (...) { throw; } }
+static void f_709() { try { f_708(); } catch (...) { throw; } }
+static void f_710() { try { f_709(); } catch (...) { throw; } }
+static void f_711() { try { f_710(); } catch (...) { throw; } }
+static void f_712() { try { f_711(); } catch (...) { throw; } }
+static void f_713() { try { f_712(); } catch (...) { throw; } }
+static void f_714() { try { f_713(); } catch (...) { throw; } }
+static void f_715() { try { f_714(); } catch (...) { throw; } }
+static void f_716() { try { f_715(); } catch (...) { throw; } }
+static void f_717() { try { f_716(); } catch (...) { throw; } }
+static void f_718() { try { f_717(); } catch (...) { throw; } }
+static void f_719() { try { f_718(); } catch (...) { throw; } }
+static void f_720() { try { f_719(); } catch (...) { throw; } }
+static void f_721() { try { f_720(); } catch (...) { throw; } }
+static void f_722() { try { f_721(); } catch (...) { throw; } }
+static void f_723() { try { f_722(); } catch (...) { throw; } }
+static void f_724() { try { f_723(); } catch (...) { throw; } }
+static void f_725() { try { f_724(); } catch (...) { throw; } }
+static void f_726() { try { f_725(); } catch (...) { throw; } }
+static void f_727() { try { f_726(); } catch (...) { throw; } }
+static void f_728() { try { f_727(); } catch (...) { throw; } }
+static void f_729() { try { f_728(); } catch (...) { throw; } }
+static void f_730() { try { f_729(); } catch (...) { throw; } }
+static void f_731() { try { f_730(); } catch (...) { throw; } }
+static void f_732() { try { f_731(); } catch (...) { throw; } }
+static void f_733() { try { f_732(); } catch (...) { throw; } }
+static void f_734() { try { f_733(); } catch (...) { throw; } }
+static void f_735() { try { f_734(); } catch (...) { throw; } }
+static void f_736() { try { f_735(); } catch (...) { throw; } }
+static void f_737() { try { f_736(); } catch (...) { throw; } }
+static void f_738() { try { f_737(); } catch (...) { throw; } }
+static void f_739() { try { f_738(); } catch (...) { throw; } }
+static void f_740() { try { f_739(); } catch (...) { throw; } }
+static void f_741() { try { f_740(); } catch (...) { throw; } }
+static void f_742() { try { f_741(); } catch (...) { throw; } }
+static void f_743() { try { f_742(); } catch (...) { throw; } }
+static void f_744() { try { f_743(); } catch (...) { throw; } }
+static void f_745() { try { f_744(); } catch (...) { throw; } }
+static void f_746() { try { f_745(); } catch (...) { throw; } }
+static void f_747() { try { f_746(); } catch (...) { throw; } }
+static void f_748() { try { f_747(); } catch (...) { throw; } }
+static void f_749() { try { f_748(); } catch (...) { throw; } }
+static void f_750() { try { f_749(); } catch (...) { throw; } }
+static void f_751() { try { f_750(); } catch (...) { throw; } }
+static void f_752() { try { f_751(); } catch (...) { throw; } }
+static void f_753() { try { f_752(); } catch (...) { throw; } }
+static void f_754() { try { f_753(); } catch (...) { throw; } }
+static void f_755() { try { f_754(); } catch (...) { throw; } }
+static void f_756() { try { f_755(); } catch (...) { throw; } }
+static void f_757() { try { f_756(); } catch (...) { throw; } }
+static void f_758() { try { f_757(); } catch (...) { throw; } }
+static void f_759() { try { f_758(); } catch (...) { throw; } }
+static void f_760() { try { f_759(); } catch (...) { throw; } }
+static void f_761() { try { f_760(); } catch (...) { throw; } }
+static void f_762() { try { f_761(); } catch (...) { throw; } }
+static void f_763() { try { f_762(); } catch (...) { throw; } }
+static void f_764() { try { f_763(); } catch (...) { throw; } }
+static void f_765() { try { f_764(); } catch (...) { throw; } }
+static void f_766() { try { f_765(); } catch (...) { throw; } }
+static void f_767() { try { f_766(); } catch (...) { throw; } }
+static void f_768() { try { f_767(); } catch (...) { throw; } }
+static void f_769() { try { f_768(); } catch (...) { throw; } }
+static void f_770() { try { f_769(); } catch (...) { throw; } }
+static void f_771() { try { f_770(); } catch (...) { throw; } }
+static void f_772() { try { f_771(); } catch (...) { throw; } }
+static void f_773() { try { f_772(); } catch (...) { throw; } }
+static void f_774() { try { f_773(); } catch (...) { throw; } }
+static void f_775() { try { f_774(); } catch (...) { throw; } }
+static void f_776() { try { f_775(); } catch (...) { throw; } }
+static void f_777() { try { f_776(); } catch (...) { throw; } }
+static void f_778() { try { f_777(); } catch (...) { throw; } }
+static void f_779() { try { f_778(); } catch (...) { throw; } }
+static void f_780() { try { f_779(); } catch (...) { throw; } }
+static void f_781() { try { f_780(); } catch (...) { throw; } }
+static void f_782() { try { f_781(); } catch (...) { throw; } }
+static void f_783() { try { f_782(); } catch (...) { throw; } }
+static void f_784() { try { f_783(); } catch (...) { throw; } }
+static void f_785() { try { f_784(); } catch (...) { throw; } }
+static void f_786() { try { f_785(); } catch (...) { throw; } }
+static void f_787() { try { f_786(); } catch (...) { throw; } }
+static void f_788() { try { f_787(); } catch (...) { throw; } }
+static void f_789() { try { f_788(); } catch (...) { throw; } }
+static void f_790() { try { f_789(); } catch (...) { throw; } }
+static void f_791() { try { f_790(); } catch (...) { throw; } }
+static void f_792() { try { f_791(); } catch (...) { throw; } }
+static void f_793() { try { f_792(); } catch (...) { throw; } }
+static void f_794() { try { f_793(); } catch (...) { throw; } }
+static void f_795() { try { f_794(); } catch (...) { throw; } }
+static void f_796() { try { f_795(); } catch (...) { throw; } }
+static void f_797() { try { f_796(); } catch (...) { throw; } }
+static void f_798() { try { f_797(); } catch (...) { throw; } }
+static void f_799() { try { f_798(); } catch (...) { throw; } }
+static void f_800() { try { f_799(); } catch (...) { throw; } }
+static void f_801() { try { f_800(); } catch (...) { throw; } }
+static void f_802() { try { f_801(); } catch (...) { throw; } }
+static void f_803() { try { f_802(); } catch (...) { throw; } }
+static void f_804() { try { f_803(); } catch (...) { throw; } }
+static void f_805() { try { f_804(); } catch (...) { throw; } }
+static void f_806() { try { f_805(); } catch (...) { throw; } }
+static void f_807() { try { f_806(); } catch (...) { throw; } }
+static void f_808() { try { f_807(); } catch (...) { throw; } }
+static void f_809() { try { f_808(); } catch (...) { throw; } }
+static void f_810() { try { f_809(); } catch (...) { throw; } }
+static void f_811() { try { f_810(); } catch (...) { throw; } }
+static void f_812() { try { f_811(); } catch (...) { throw; } }
+static void f_813() { try { f_812(); } catch (...) { throw; } }
+static void f_814() { try { f_813(); } catch (...) { throw; } }
+static void f_815() { try { f_814(); } catch (...) { throw; } }
+static void f_816() { try { f_815(); } catch (...) { throw; } }
+static void f_817() { try { f_816(); } catch (...) { throw; } }
+static void f_818() { try { f_817(); } catch (...) { throw; } }
+static void f_819() { try { f_818(); } catch (...) { throw; } }
+static void f_820() { try { f_819(); } catch (...) { throw; } }
+static void f_821() { try { f_820(); } catch (...) { throw; } }
+static void f_822() { try { f_821(); } catch (...) { throw; } }
+static void f_823() { try { f_822(); } catch (...) { throw; } }
+static void f_824() { try { f_823(); } catch (...) { throw; } }
+static void f_825() { try { f_824(); } catch (...) { throw; } }
+static void f_826() { try { f_825(); } catch (...) { throw; } }
+static void f_827() { try { f_826(); } catch (...) { throw; } }
+static void f_828() { try { f_827(); } catch (...) { throw; } }
+static void f_829() { try { f_828(); } catch (...) { throw; } }
+static void f_830() { try { f_829(); } catch (...) { throw; } }
+static void f_831() { try { f_830(); } catch (...) { throw; } }
+static void f_832() { try { f_831(); } catch (...) { throw; } }
+static void f_833() { try { f_832(); } catch (...) { throw; } }
+static void f_834() { try { f_833(); } catch (...) { throw; } }
+static void f_835() { try { f_834(); } catch (...) { throw; } }
+static void f_836() { try { f_835(); } catch (...) { throw; } }
+static void f_837() { try { f_836(); } catch (...) { throw; } }
+static void f_838() { try { f_837(); } catch (...) { throw; } }
+static void f_839() { try { f_838(); } catch (...) { throw; } }
+static void f_840() { try { f_839(); } catch (...) { throw; } }
+static void f_841() { try { f_840(); } catch (...) { throw; } }
+static void f_842() { try { f_841(); } catch (...) { throw; } }
+static void f_843() { try { f_842(); } catch (...) { throw; } }
+static void f_844() { try { f_843(); } catch (...) { throw; } }
+static void f_845() { try { f_844(); } catch (...) { throw; } }
+static void f_846() { try { f_845(); } catch (...) { throw; } }
+static void f_847() { try { f_846(); } catch (...) { throw; } }
+static void f_848() { try { f_847(); } catch (...) { throw; } }
+static void f_849() { try { f_848(); } catch (...) { throw; } }
+static void f_850() { try { f_849(); } catch (...) { throw; } }
+static void f_851() { try { f_850(); } catch (...) { throw; } }
+static void f_852() { try { f_851(); } catch (...) { throw; } }
+static void f_853() { try { f_852(); } catch (...) { throw; } }
+static void f_854() { try { f_853(); } catch (...) { throw; } }
+static void f_855() { try { f_854(); } catch (...) { throw; } }
+static void f_856() { try { f_855(); } catch (...) { throw; } }
+static void f_857() { try { f_856(); } catch (...) { throw; } }
+static void f_858() { try { f_857(); } catch (...) { throw; } }
+static void f_859() { try { f_858(); } catch (...) { throw; } }
+static void f_860() { try { f_859(); } catch (...) { throw; } }
+static void f_861() { try { f_860(); } catch (...) { throw; } }
+static void f_862() { try { f_861(); } catch (...) { throw; } }
+static void f_863() { try { f_862(); } catch (...) { throw; } }
+static void f_864() { try { f_863(); } catch (...) { throw; } }
+static void f_865() { try { f_864(); } catch (...) { throw; } }
+static void f_866() { try { f_865(); } catch (...) { throw; } }
+static void f_867() { try { f_866(); } catch (...) { throw; } }
+static void f_868() { try { f_867(); } catch (...) { throw; } }
+static void f_869() { try { f_868(); } catch (...) { throw; } }
+static void f_870() { try { f_869(); } catch (...) { throw; } }
+static void f_871() { try { f_870(); } catch (...) { throw; } }
+static void f_872() { try { f_871(); } catch (...) { throw; } }
+static void f_873() { try { f_872(); } catch (...) { throw; } }
+static void f_874() { try { f_873(); } catch (...) { throw; } }
+static void f_875() { try { f_874(); } catch (...) { throw; } }
+static void f_876() { try { f_875(); } catch (...) { throw; } }
+static void f_877() { try { f_876(); } catch (...) { throw; } }
+static void f_878() { try { f_877(); } catch (...) { throw; } }
+static void f_879() { try { f_878(); } catch (...) { throw; } }
+static void f_880() { try { f_879(); } catch (...) { throw; } }
+static void f_881() { try { f_880(); } catch (...) { throw; } }
+static void f_882() { try { f_881(); } catch (...) { throw; } }
+static void f_883() { try { f_882(); } catch (...) { throw; } }
+static void f_884() { try { f_883(); } catch (...) { throw; } }
+static void f_885() { try { f_884(); } catch (...) { throw; } }
+static void f_886() { try { f_885(); } catch (...) { throw; } }
+static void f_887() { try { f_886(); } catch (...) { throw; } }
+static void f_888() { try { f_887(); } catch (...) { throw; } }
+static void f_889() { try { f_888(); } catch (...) { throw; } }
+static void f_890() { try { f_889(); } catch (...) { throw; } }
+static void f_891() { try { f_890(); } catch (...) { throw; } }
+static void f_892() { try { f_891(); } catch (...) { throw; } }
+static void f_893() { try { f_892(); } catch (...) { throw; } }
+static void f_894() { try { f_893(); } catch (...) { throw; } }
+static void f_895() { try { f_894(); } catch (...) { throw; } }
+static void f_896() { try { f_895(); } catch (...) { throw; } }
+static void f_897() { try { f_896(); } catch (...) { throw; } }
+static void f_898() { try { f_897(); } catch (...) { throw; } }
+static void f_899() { try { f_898(); } catch (...) { throw; } }
+static void f_900() { try { f_899(); } catch (...) { throw; } }
+static void f_901() { try { f_900(); } catch (...) { throw; } }
+static void f_902() { try { f_901(); } catch (...) { throw; } }
+static void f_903() { try { f_902(); } catch (...) { throw; } }
+static void f_904() { try { f_903(); } catch (...) { throw; } }
+static void f_905() { try { f_904(); } catch (...) { throw; } }
+static void f_906() { try { f_905(); } catch (...) { throw; } }
+static void f_907() { try { f_906(); } catch (...) { throw; } }
+static void f_908() { try { f_907(); } catch (...) { throw; } }
+static void f_909() { try { f_908(); } catch (...) { throw; } }
+static void f_910() { try { f_909(); } catch (...) { throw; } }
+static void f_911() { try { f_910(); } catch (...) { throw; } }
+static void f_912() { try { f_911(); } catch (...) { throw; } }
+static void f_913() { try { f_912(); } catch (...) { throw; } }
+static void f_914() { try { f_913(); } catch (...) { throw; } }
+static void f_915() { try { f_914(); } catch (...) { throw; } }
+static void f_916() { try { f_915(); } catch (...) { throw; } }
+static void f_917() { try { f_916(); } catch (...) { throw; } }
+static void f_918() { try { f_917(); } catch (...) { throw; } }
+static void f_919() { try { f_918(); } catch (...) { throw; } }
+static void f_920() { try { f_919(); } catch (...) { throw; } }
+static void f_921() { try { f_920(); } catch (...) { throw; } }
+static void f_922() { try { f_921(); } catch (...) { throw; } }
+static void f_923() { try { f_922(); } catch (...) { throw; } }
+static void f_924() { try { f_923(); } catch (...) { throw; } }
+static void f_925() { try { f_924(); } catch (...) { throw; } }
+static void f_926() { try { f_925(); } catch (...) { throw; } }
+static void f_927() { try { f_926(); } catch (...) { throw; } }
+static void f_928() { try { f_927(); } catch (...) { throw; } }
+static void f_929() { try { f_928(); } catch (...) { throw; } }
+static void f_930() { try { f_929(); } catch (...) { throw; } }
+static void f_931() { try { f_930(); } catch (...) { throw; } }
+static void f_932() { try { f_931(); } catch (...) { throw; } }
+static void f_933() { try { f_932(); } catch (...) { throw; } }
+static void f_934() { try { f_933(); } catch (...) { throw; } }
+static void f_935() { try { f_934(); } catch (...) { throw; } }
+static void f_936() { try { f_935(); } catch (...) { throw; } }
+static void f_937() { try { f_936(); } catch (...) { throw; } }
+static void f_938() { try { f_937(); } catch (...) { throw; } }
+static void f_939() { try { f_938(); } catch (...) { throw; } }
+static void f_940() { try { f_939(); } catch (...) { throw; } }
+static void f_941() { try { f_940(); } catch (...) { throw; } }
+static void f_942() { try { f_941(); } catch (...) { throw; } }
+static void f_943() { try { f_942(); } catch (...) { throw; } }
+static void f_944() { try { f_943(); } catch (...) { throw; } }
+static void f_945() { try { f_944(); } catch (...) { throw; } }
+static void f_946() { try { f_945(); } catch (...) { throw; } }
+static void f_947() { try { f_946(); } catch (...) { throw; } }
+static void f_948() { try { f_947(); } catch (...) { throw; } }
+static void f_949() { try { f_948(); } catch (...) { throw; } }
+static void f_950() { try { f_949(); } catch (...) { throw; } }
+static void f_951() { try { f_950(); } catch (...) { throw; } }
+static void f_952() { try { f_951(); } catch (...) { throw; } }
+static void f_953() { try { f_952(); } catch (...) { throw; } }
+static void f_954() { try { f_953(); } catch (...) { throw; } }
+static void f_955() { try { f_954(); } catch (...) { throw; } }
+static void f_956() { try { f_955(); } catch (...) { throw; } }
+static void f_957() { try { f_956(); } catch (...) { throw; } }
+static void f_958() { try { f_957(); } catch (...) { throw; } }
+static void f_959() { try { f_958(); } catch (...) { throw; } }
+static void f_960() { try { f_959(); } catch (...) { throw; } }
+static void f_961() { try { f_960(); } catch (...) { throw; } }
+static void f_962() { try { f_961(); } catch (...) { throw; } }
+static void f_963() { try { f_962(); } catch (...) { throw; } }
+static void f_964() { try { f_963(); } catch (...) { throw; } }
+static void f_965() { try { f_964(); } catch (...) { throw; } }
+static void f_966() { try { f_965(); } catch (...) { throw; } }
+static void f_967() { try { f_966(); } catch (...) { throw; } }
+static void f_968() { try { f_967(); } catch (...) { throw; } }
+static void f_969() { try { f_968(); } catch (...) { throw; } }
+static void f_970() { try { f_969(); } catch (...) { throw; } }
+static void f_971() { try { f_970(); } catch (...) { throw; } }
+static void f_972() { try { f_971(); } catch (...) { throw; } }
+static void f_973() { try { f_972(); } catch (...) { throw; } }
+static void f_974() { try { f_973(); } catch (...) { throw; } }
+static void f_975() { try { f_974(); } catch (...) { throw; } }
+static void f_976() { try { f_975(); } catch (...) { throw; } }
+static void f_977() { try { f_976(); } catch (...) { throw; } }
+static void f_978() { try { f_977(); } catch (...) { throw; } }
+static void f_979() { try { f_978(); } catch (...) { throw; } }
+static void f_980() { try { f_979(); } catch (...) { throw; } }
+static void f_981() { try { f_980(); } catch (...) { throw; } }
+static void f_982() { try { f_981(); } catch (...) { throw; } }
+static void f_983() { try { f_982(); } catch (...) { throw; } }
+static void f_984() { try { f_983(); } catch (...) { throw; } }
+static void f_985() { try { f_984(); } catch (...) { throw; } }
+static void f_986() { try { f_985(); } catch (...) { throw; } }
+static void f_987() { try { f_986(); } catch (...) { throw; } }
+static void f_988() { try { f_987(); } catch (...) { throw; } }
+static void f_989() { try { f_988(); } catch (...) { throw; } }
+static void f_990() { try { f_989(); } catch (...) { throw; } }
+static void f_991() { try { f_990(); } catch (...) { throw; } }
+static void f_992() { try { f_991(); } catch (...) { throw; } }
+static void f_993() { try { f_992(); } catch (...) { throw; } }
+static void f_994() { try { f_993(); } catch (...) { throw; } }
+static void f_995() { try { f_994(); } catch (...) { throw; } }
+static void f_996() { try { f_995(); } catch (...) { throw; } }
+static void f_997() { try { f_996(); } catch (...) { throw; } }
+static void f_998() { try { f_997(); } catch (...) { throw; } }
+static void f_999() { try { f_998(); } catch (...) { throw; } }
+static void f_1000() { try { f_999(); } catch (...) { throw; } }
+static void f_1001() { try { f_1000(); } catch (...) { throw; } }
+static void f_1002() { try { f_1001(); } catch (...) { throw; } }
+static void f_1003() { try { f_1002(); } catch (...) { throw; } }
+static void f_1004() { try { f_1003(); } catch (...) { throw; } }
+static void f_1005() { try { f_1004(); } catch (...) { throw; } }
+static void f_1006() { try { f_1005(); } catch (...) { throw; } }
+static void f_1007() { try { f_1006(); } catch (...) { throw; } }
+static void f_1008() { try { f_1007(); } catch (...) { throw; } }
+static void f_1009() { try { f_1008(); } catch (...) { throw; } }
+static void f_1010() { try { f_1009(); } catch (...) { throw; } }
+static void f_1011() { try { f_1010(); } catch (...) { throw; } }
+static void f_1012() { try { f_1011(); } catch (...) { throw; } }
+static void f_1013() { try { f_1012(); } catch (...) { throw; } }
+static void f_1014() { try { f_1013(); } catch (...) { throw; } }
+static void f_1015() { try { f_1014(); } catch (...) { throw; } }
+static void f_1016() { try { f_1015(); } catch (...) { throw; } }
+static void f_1017() { try { f_1016(); } catch (...) { throw; } }
+static void f_1018() { try { f_1017(); } catch (...) { throw; } }
+static void f_1019() { try { f_1018(); } catch (...) { throw; } }
+static void f_1020() { try { f_1019(); } catch (...) { throw; } }
+int main(int argc, char *argv[]) {
+ try {
+ f_1020();
+ } catch (int n) {
+ return 42 - n;
+ }
+ return 1;
+}
+
diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
index dc3ed942aa8ac8a..a2c0c13cdbf66b9 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
+++ b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
@@ -510,8 +510,9 @@ template <typename CURecTraits> class CompactUnwindManager {
// If this record marks the start of a new second level page.
if (RecordIdx % NumRecordsPerSecondLevelPage == 0) {
auto FnDelta = R.Fn->getAddress() - CompactUnwindBase->getAddress();
- auto SecondLevelPageOffset = SectionOffsetToSecondLevelPages +
- (RecordIdx / NumRecordsPerSecondLevelPage);
+ auto SecondLevelPageOffset =
+ SectionOffsetToSecondLevelPages +
+ SecondLevelPageSize * (RecordIdx / NumRecordsPerSecondLevelPage);
auto LSDAOffset =
SectionOffsetToLSDAs + NumPreviousLSDAs * LSDAEntrySize;
>From 614163f51b24c66eb2c825d153988c380551ebb3 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 14:24:17 +1100
Subject: [PATCH 11/14] [JITLink] Add a jitlink::Symbol::getSection()
convenience method.
`Sym.getSection()` is equivalent to `Sym.getBlock().getSection()`.
(cherry picked from commit 4a2a8ed70da7ec44f0aa9092595e5b0f81a7e841)
---
.../llvm/ExecutionEngine/JITLink/JITLink.h | 11 ++++---
.../ExecutionEngine/JITLink/COFF_x86_64.cpp | 3 +-
.../JITLink/CompactUnwindSupport.h | 2 +-
llvm/lib/ExecutionEngine/JITLink/JITLink.cpp | 2 +-
.../ExecutionEngine/JITLink/JITLinkGeneric.h | 2 +-
llvm/lib/ExecutionEngine/JITLink/aarch32.cpp | 6 ++--
.../Orc/Debugging/PerfSupportPlugin.cpp | 2 +-
.../Orc/Debugging/VTuneSupportPlugin.cpp | 2 +-
.../lib/ExecutionEngine/Orc/MachOPlatform.cpp | 2 +-
.../JITLink/LinkGraphTests.cpp | 30 +++++++++++++++++++
10 files changed, 47 insertions(+), 15 deletions(-)
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
index 297e603164b2440..8f0dfea0c97ac0d 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLink.h
@@ -587,6 +587,9 @@ class Symbol {
return static_cast<const Block &>(*Base);
}
+ /// Return the Section for this Symbol (Symbol must be defined).
+ Section &getSection() const { return getBlock().getSection(); }
+
/// Returns the offset for this symbol within the underlying addressable.
orc::ExecutorAddrDiff getOffset() const { return Offset; }
@@ -1460,7 +1463,7 @@ class LinkGraph {
A.setAddress(orc::ExecutorAddr());
} else {
assert(Sym.isDefined() && "Sym is not a defined symbol");
- Section &Sec = Sym.getBlock().getSection();
+ Section &Sec = Sym.getSection();
Sec.removeSymbol(Sym);
Sym.makeExternal(createAddressable(orc::ExecutorAddr(), false));
}
@@ -1488,7 +1491,7 @@ class LinkGraph {
Sym.setScope(Scope::Local);
} else {
assert(Sym.isDefined() && "Sym is not a defined symbol");
- Section &Sec = Sym.getBlock().getSection();
+ Section &Sec = Sym.getSection();
Sec.removeSymbol(Sym);
Sym.makeAbsolute(createAddressable(Address));
}
@@ -1534,7 +1537,7 @@ class LinkGraph {
transferDefinedSymbol(Symbol &Sym, Block &DestBlock,
orc::ExecutorAddrDiff NewOffset,
std::optional<orc::ExecutorAddrDiff> ExplicitNewSize) {
- auto &OldSection = Sym.getBlock().getSection();
+ auto &OldSection = Sym.getSection();
Sym.setBlock(DestBlock);
Sym.setOffset(NewOffset);
if (ExplicitNewSize)
@@ -1622,7 +1625,7 @@ class LinkGraph {
/// Removes defined symbols. Does not remove the underlying block.
void removeDefinedSymbol(Symbol &Sym) {
assert(Sym.isDefined() && "Sym is not a defined symbol");
- Sym.getBlock().getSection().removeSymbol(Sym);
+ Sym.getSection().removeSymbol(Sym);
destroySymbol(Sym);
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
index 151f1b337087d12..8ceb08051e423e1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
@@ -221,8 +221,7 @@ class COFFLinkGraphLowering_x86_64 {
}
case EdgeKind_coff_x86_64::SecRel32: {
E.setAddend(E.getAddend() -
- getSectionStart(E.getTarget().getBlock().getSection())
- .getValue());
+ getSectionStart(E.getTarget().getSection()).getValue());
E.setKind(x86_64::Pointer32);
break;
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
index a2c0c13cdbf66b9..c306264b6da5d26 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
+++ b/llvm/lib/ExecutionEngine/JITLink/CompactUnwindSupport.h
@@ -155,7 +155,7 @@ template <typename CURecTraits> class CompactUnwindManager {
Edge *KeepAliveEdge = nullptr;
for (auto &E : Fn.getBlock().edges_at(0)) {
if (E.getKind() == Edge::KeepAlive && E.getTarget().isDefined() &&
- &E.getTarget().getBlock().getSection() == EHFrameSec) {
+ &E.getTarget().getSection() == EHFrameSec) {
KeepAliveEdge = &E;
break;
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index 6b77330bb764b34..e8ce9b2b9527d45 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -424,7 +424,7 @@ Error makeTargetOutOfRangeError(const LinkGraph &G, const Block &B,
if (E.getTarget().hasName()) {
ErrStream << "\"" << E.getTarget().getName() << "\"";
} else
- ErrStream << E.getTarget().getBlock().getSection().getName() << " + "
+ ErrStream << E.getTarget().getSection().getName() << " + "
<< formatv("{0:x}", E.getOffset());
ErrStream << " at address " << formatv("{0:x}", E.getTarget().getAddress())
<< " is out of range of " << G.getEdgeKindName(E.getKind())
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
index e5d05e6b1b7bfc6..0bf714d6fcdf3ce 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLinkGeneric.h
@@ -162,7 +162,7 @@ template <typename LinkerImpl> class JITLinker : public JITLinkerBase {
// If B is a block in a Standard or Finalize section then make sure
// that no edges point to symbols in NoAlloc sections.
assert((NoAllocSection || !E.getTarget().isDefined() ||
- E.getTarget().getBlock().getSection().getMemLifetime() !=
+ E.getTarget().getSection().getMemLifetime() !=
orc::MemLifetime::NoAlloc) &&
"Block in allocated section has edge pointing to no-alloc "
"section");
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
index 7b255717f238383..01bb6e0403578bd 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch32.cpp
@@ -874,7 +874,7 @@ bool StubsManager_prev7::visitEdge(LinkGraph &G, Block *B, Edge &E) {
LLVM_DEBUG({
dbgs() << " Using " << (UseThumb ? "Thumb" : "Arm") << " entrypoint "
<< *StubEntrypoint << " in "
- << StubEntrypoint->getBlock().getSection().getName() << "\n";
+ << StubEntrypoint->getSection().getName() << "\n";
});
E.setTarget(*StubEntrypoint);
@@ -919,8 +919,8 @@ bool StubsManager_v7::visitEdge(LinkGraph &G, Block *B, Edge &E) {
"Instruction set states of stub and relocation site should be equal");
LLVM_DEBUG({
dbgs() << " Using " << (MakeThumb ? "Thumb" : "Arm") << " entry "
- << *StubSymbol << " in "
- << StubSymbol->getBlock().getSection().getName() << "\n";
+ << *StubSymbol << " in " << StubSymbol->getSection().getName()
+ << "\n";
});
E.setTarget(*StubSymbol);
diff --git a/llvm/lib/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.cpp
index 7a970f3cccf4616..bc5b3bb538e39c6 100644
--- a/llvm/lib/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.cpp
@@ -113,7 +113,7 @@ getCodeLoadRecord(const Symbol &Sym, std::atomic<uint64_t> &CodeIndex) {
static std::optional<PerfJITDebugInfoRecord>
getDebugInfoRecord(const Symbol &Sym, DWARFContext &DC) {
- auto &Section = Sym.getBlock().getSection();
+ auto &Section = Sym.getSection();
auto Addr = Sym.getAddress();
auto Size = Sym.getSize();
auto SAddr = object::SectionedAddress{Addr.getValue(), Section.getOrdinal()};
diff --git a/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
index 9715a503629bf57..1f4557217cf246c 100644
--- a/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.cpp
@@ -63,7 +63,7 @@ static VTuneMethodBatch getMethodBatch(LinkGraph &G, bool EmitDebugInfo) {
if (!EmitDebugInfo)
continue;
- auto &Section = Sym->getBlock().getSection();
+ auto &Section = Sym->getSection();
auto Addr = Sym->getAddress();
auto SAddr =
object::SectionedAddress{Addr.getValue(), Section.getOrdinal()};
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 44ae73671f5b15a..845990d965b16d3 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -1071,7 +1071,7 @@ Error MachOPlatform::MachOPlatformPlugin::processObjCImageInfo(
for (auto *B : Sec.blocks())
for (auto &E : B->edges())
if (E.getTarget().isDefined() &&
- &E.getTarget().getBlock().getSection() == ObjCImageInfo)
+ &E.getTarget().getSection() == ObjCImageInfo)
return make_error<StringError>(MachOObjCImageInfoSectionName +
" is referenced within file " +
G.getName(),
diff --git a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
index fb60acddf7821e6..c76087349352820 100644
--- a/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
+++ b/llvm/unittests/ExecutionEngine/JITLink/LinkGraphTests.cpp
@@ -54,6 +54,36 @@ TEST(LinkGraphTest, AddressAccess) {
EXPECT_EQ(B1.getFixupAddress(E1), B1Addr + 8) << "Incorrect fixup address";
}
+TEST(LinkGraphTest, DefinedSymbolProperties) {
+ // Check that Section::empty behaves as expected.
+ LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),
+ Triple("x86_64-apple-darwin"), SubtargetFeatures(),
+ getGenericEdgeKindName);
+ auto &Sec =
+ G.createSection("__data", orc::MemProt::Read | orc::MemProt::Write);
+ auto &B =
+ G.createContentBlock(Sec, BlockContent, orc::ExecutorAddr(0x1000), 8, 0);
+ auto &S = G.addDefinedSymbol(B, 0, "sym", 4, Linkage::Strong, Scope::Default,
+ false, false);
+
+ EXPECT_TRUE(S.hasName());
+ EXPECT_EQ(*S.getName(), "sym");
+ EXPECT_TRUE(S.isDefined());
+ EXPECT_FALSE(S.isLive());
+ EXPECT_FALSE(S.isCallable());
+ EXPECT_FALSE(S.isExternal());
+ EXPECT_FALSE(S.isAbsolute());
+ EXPECT_EQ(&S.getBlock(), &B);
+ EXPECT_EQ(&S.getSection(), &Sec);
+ EXPECT_EQ(S.getOffset(), 0U);
+ EXPECT_EQ(S.getSize(), 4U);
+ EXPECT_EQ(S.getRange(), orc::ExecutorAddrRange(B.getAddress(), 4));
+ EXPECT_EQ(S.getSymbolContent(), BlockContent.slice(0, 4));
+ EXPECT_EQ(S.getLinkage(), Linkage::Strong);
+ EXPECT_EQ(S.getScope(), Scope::Default);
+ EXPECT_EQ(S.getTargetFlags(), 0U);
+}
+
TEST(LinkGraphTest, SectionEmpty) {
// Check that Section::empty behaves as expected.
LinkGraph G("foo", std::make_shared<orc::SymbolStringPool>(),
>From f28f62a7d51eecda941cbd9e48883ebb56e566f0 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 16:04:35 +1100
Subject: [PATCH 12/14] [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.
(cherry picked from commit 9d88ffe7f7b4a46d3bcb7bbdf0d7eb037ab5ba04)
---
.../JITLink/CompactUnwindSupport.h | 54 ++++++++++++++-----
.../ExecutionEngine/JITLink/MachO_arm64.cpp | 1 +
.../ExecutionEngine/JITLink/MachO_x86_64.cpp | 1 +
...-throw-catch.ll => throw-catch-minimal.ll} | 0
4 files changed, 43 insertions(+), 13 deletions(-)
rename llvm/test/ExecutionEngine/Orc/{minimal-throw-catch.ll => throw-catch-minimal.ll} (100%)
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
>From 626df9e89de6a1fca20eb808c2c0a8d785b1cd1a Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 17:01:36 +1100
Subject: [PATCH 13/14] [JITLink] Add missing testcase for
compact-unwind-needs-dwarf.
This testcase was accidentally left out of 9d88ffe7f7b.
(cherry picked from commit 7a213e70eb24e621042f2fda043622048cb1f1df)
---
.../Orc/throw-catch-no-frame-pointer.ll | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 llvm/test/ExecutionEngine/Orc/throw-catch-no-frame-pointer.ll
diff --git a/llvm/test/ExecutionEngine/Orc/throw-catch-no-frame-pointer.ll b/llvm/test/ExecutionEngine/Orc/throw-catch-no-frame-pointer.ll
new file mode 100644
index 000000000000000..8032e71ad2f35c3
--- /dev/null
+++ b/llvm/test/ExecutionEngine/Orc/throw-catch-no-frame-pointer.ll
@@ -0,0 +1,51 @@
+; REQUIRES: system-darwin && host-unwind-supports-jit
+; RUN: lli -jit-kind=orc %s
+;
+; Check that we can throw exceptions from no-fp functions. On systems that
+; support compact-unwind this implicitly tests that we correctly handle
+; unwind-info records that depend on DWARF FDEs.
+
+ at _ZTIi = external constant ptr
+
+declare ptr @__cxa_allocate_exception(i64)
+declare void @__cxa_throw(ptr, ptr, ptr)
+declare ptr @__cxa_begin_catch(ptr)
+declare void @__cxa_end_catch()
+declare i32 @__gxx_personality_v0(...)
+declare i32 @llvm.eh.typeid.for.p0(ptr)
+
+define void @_Z3foov() "frame-pointer"="none" {
+entry:
+ %exception = tail call ptr @__cxa_allocate_exception(i64 4)
+ store i32 42, ptr %exception
+ tail call void @__cxa_throw(ptr %exception, ptr nonnull @_ZTIi, ptr null)
+ unreachable
+}
+
+define i32 @main(i32 %argc, ptr %argv) "frame-pointer"="all" personality ptr @__gxx_personality_v0 {
+entry:
+ invoke void @_Z3foov()
+ to label %return.unreachable unwind label %lpad
+
+lpad:
+ %0 = landingpad { ptr, i32 }
+ catch ptr @_ZTIi
+ %1 = extractvalue { ptr, i32 } %0, 1
+ %2 = tail call i32 @llvm.eh.typeid.for.p0(ptr nonnull @_ZTIi)
+ %matches = icmp eq i32 %1, %2
+ br i1 %matches, label %catch, label %eh.resume
+
+catch:
+ %3 = extractvalue { ptr, i32 } %0, 0
+ %4 = tail call ptr @__cxa_begin_catch(ptr %3)
+ %5 = load i32, ptr %4
+ %sub = sub nsw i32 42, %5
+ tail call void @__cxa_end_catch()
+ ret i32 %sub
+
+return.unreachable:
+ unreachable
+
+eh.resume:
+ resume { ptr, i32 } %0
+}
>From d4cfb561e2c4a39a1715fea0a4bc844056e4b3b0 Mon Sep 17 00:00:00 2001
From: Lang Hames <lhames at gmail.com>
Date: Thu, 6 Feb 2025 17:06:03 +1100
Subject: [PATCH 14/14] [ORC-RT] Use templates to express deeply nested
function calls in testcase.
Makes this test smaller and more readable.
(cherry picked from commit e00f824e9a5ea73830bd346115968fa9ace84cbf)
---
.../Generic/exceptions-stress-test-tower.cpp | 1029 +----------------
1 file changed, 7 insertions(+), 1022 deletions(-)
diff --git a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
index f7a39a9dccd6fcb..245afa084f5c0ea 100644
--- a/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
+++ b/compiler-rt/test/orc/TestCases/Darwin/Generic/exceptions-stress-test-tower.cpp
@@ -7,1030 +7,15 @@
// stack frames. The number (1022) is chosen to force emission of multiple
// unwind info second-level pages.
-static void f_0() { throw 42; }
-static void f_1() { try { f_0(); } catch (...) { throw; } }
-static void f_2() { try { f_1(); } catch (...) { throw; } }
-static void f_3() { try { f_2(); } catch (...) { throw; } }
-static void f_4() { try { f_3(); } catch (...) { throw; } }
-static void f_5() { try { f_4(); } catch (...) { throw; } }
-static void f_6() { try { f_5(); } catch (...) { throw; } }
-static void f_7() { try { f_6(); } catch (...) { throw; } }
-static void f_8() { try { f_7(); } catch (...) { throw; } }
-static void f_9() { try { f_8(); } catch (...) { throw; } }
-static void f_10() { try { f_9(); } catch (...) { throw; } }
-static void f_11() { try { f_10(); } catch (...) { throw; } }
-static void f_12() { try { f_11(); } catch (...) { throw; } }
-static void f_13() { try { f_12(); } catch (...) { throw; } }
-static void f_14() { try { f_13(); } catch (...) { throw; } }
-static void f_15() { try { f_14(); } catch (...) { throw; } }
-static void f_16() { try { f_15(); } catch (...) { throw; } }
-static void f_17() { try { f_16(); } catch (...) { throw; } }
-static void f_18() { try { f_17(); } catch (...) { throw; } }
-static void f_19() { try { f_18(); } catch (...) { throw; } }
-static void f_20() { try { f_19(); } catch (...) { throw; } }
-static void f_21() { try { f_20(); } catch (...) { throw; } }
-static void f_22() { try { f_21(); } catch (...) { throw; } }
-static void f_23() { try { f_22(); } catch (...) { throw; } }
-static void f_24() { try { f_23(); } catch (...) { throw; } }
-static void f_25() { try { f_24(); } catch (...) { throw; } }
-static void f_26() { try { f_25(); } catch (...) { throw; } }
-static void f_27() { try { f_26(); } catch (...) { throw; } }
-static void f_28() { try { f_27(); } catch (...) { throw; } }
-static void f_29() { try { f_28(); } catch (...) { throw; } }
-static void f_30() { try { f_29(); } catch (...) { throw; } }
-static void f_31() { try { f_30(); } catch (...) { throw; } }
-static void f_32() { try { f_31(); } catch (...) { throw; } }
-static void f_33() { try { f_32(); } catch (...) { throw; } }
-static void f_34() { try { f_33(); } catch (...) { throw; } }
-static void f_35() { try { f_34(); } catch (...) { throw; } }
-static void f_36() { try { f_35(); } catch (...) { throw; } }
-static void f_37() { try { f_36(); } catch (...) { throw; } }
-static void f_38() { try { f_37(); } catch (...) { throw; } }
-static void f_39() { try { f_38(); } catch (...) { throw; } }
-static void f_40() { try { f_39(); } catch (...) { throw; } }
-static void f_41() { try { f_40(); } catch (...) { throw; } }
-static void f_42() { try { f_41(); } catch (...) { throw; } }
-static void f_43() { try { f_42(); } catch (...) { throw; } }
-static void f_44() { try { f_43(); } catch (...) { throw; } }
-static void f_45() { try { f_44(); } catch (...) { throw; } }
-static void f_46() { try { f_45(); } catch (...) { throw; } }
-static void f_47() { try { f_46(); } catch (...) { throw; } }
-static void f_48() { try { f_47(); } catch (...) { throw; } }
-static void f_49() { try { f_48(); } catch (...) { throw; } }
-static void f_50() { try { f_49(); } catch (...) { throw; } }
-static void f_51() { try { f_50(); } catch (...) { throw; } }
-static void f_52() { try { f_51(); } catch (...) { throw; } }
-static void f_53() { try { f_52(); } catch (...) { throw; } }
-static void f_54() { try { f_53(); } catch (...) { throw; } }
-static void f_55() { try { f_54(); } catch (...) { throw; } }
-static void f_56() { try { f_55(); } catch (...) { throw; } }
-static void f_57() { try { f_56(); } catch (...) { throw; } }
-static void f_58() { try { f_57(); } catch (...) { throw; } }
-static void f_59() { try { f_58(); } catch (...) { throw; } }
-static void f_60() { try { f_59(); } catch (...) { throw; } }
-static void f_61() { try { f_60(); } catch (...) { throw; } }
-static void f_62() { try { f_61(); } catch (...) { throw; } }
-static void f_63() { try { f_62(); } catch (...) { throw; } }
-static void f_64() { try { f_63(); } catch (...) { throw; } }
-static void f_65() { try { f_64(); } catch (...) { throw; } }
-static void f_66() { try { f_65(); } catch (...) { throw; } }
-static void f_67() { try { f_66(); } catch (...) { throw; } }
-static void f_68() { try { f_67(); } catch (...) { throw; } }
-static void f_69() { try { f_68(); } catch (...) { throw; } }
-static void f_70() { try { f_69(); } catch (...) { throw; } }
-static void f_71() { try { f_70(); } catch (...) { throw; } }
-static void f_72() { try { f_71(); } catch (...) { throw; } }
-static void f_73() { try { f_72(); } catch (...) { throw; } }
-static void f_74() { try { f_73(); } catch (...) { throw; } }
-static void f_75() { try { f_74(); } catch (...) { throw; } }
-static void f_76() { try { f_75(); } catch (...) { throw; } }
-static void f_77() { try { f_76(); } catch (...) { throw; } }
-static void f_78() { try { f_77(); } catch (...) { throw; } }
-static void f_79() { try { f_78(); } catch (...) { throw; } }
-static void f_80() { try { f_79(); } catch (...) { throw; } }
-static void f_81() { try { f_80(); } catch (...) { throw; } }
-static void f_82() { try { f_81(); } catch (...) { throw; } }
-static void f_83() { try { f_82(); } catch (...) { throw; } }
-static void f_84() { try { f_83(); } catch (...) { throw; } }
-static void f_85() { try { f_84(); } catch (...) { throw; } }
-static void f_86() { try { f_85(); } catch (...) { throw; } }
-static void f_87() { try { f_86(); } catch (...) { throw; } }
-static void f_88() { try { f_87(); } catch (...) { throw; } }
-static void f_89() { try { f_88(); } catch (...) { throw; } }
-static void f_90() { try { f_89(); } catch (...) { throw; } }
-static void f_91() { try { f_90(); } catch (...) { throw; } }
-static void f_92() { try { f_91(); } catch (...) { throw; } }
-static void f_93() { try { f_92(); } catch (...) { throw; } }
-static void f_94() { try { f_93(); } catch (...) { throw; } }
-static void f_95() { try { f_94(); } catch (...) { throw; } }
-static void f_96() { try { f_95(); } catch (...) { throw; } }
-static void f_97() { try { f_96(); } catch (...) { throw; } }
-static void f_98() { try { f_97(); } catch (...) { throw; } }
-static void f_99() { try { f_98(); } catch (...) { throw; } }
-static void f_100() { try { f_99(); } catch (...) { throw; } }
-static void f_101() { try { f_100(); } catch (...) { throw; } }
-static void f_102() { try { f_101(); } catch (...) { throw; } }
-static void f_103() { try { f_102(); } catch (...) { throw; } }
-static void f_104() { try { f_103(); } catch (...) { throw; } }
-static void f_105() { try { f_104(); } catch (...) { throw; } }
-static void f_106() { try { f_105(); } catch (...) { throw; } }
-static void f_107() { try { f_106(); } catch (...) { throw; } }
-static void f_108() { try { f_107(); } catch (...) { throw; } }
-static void f_109() { try { f_108(); } catch (...) { throw; } }
-static void f_110() { try { f_109(); } catch (...) { throw; } }
-static void f_111() { try { f_110(); } catch (...) { throw; } }
-static void f_112() { try { f_111(); } catch (...) { throw; } }
-static void f_113() { try { f_112(); } catch (...) { throw; } }
-static void f_114() { try { f_113(); } catch (...) { throw; } }
-static void f_115() { try { f_114(); } catch (...) { throw; } }
-static void f_116() { try { f_115(); } catch (...) { throw; } }
-static void f_117() { try { f_116(); } catch (...) { throw; } }
-static void f_118() { try { f_117(); } catch (...) { throw; } }
-static void f_119() { try { f_118(); } catch (...) { throw; } }
-static void f_120() { try { f_119(); } catch (...) { throw; } }
-static void f_121() { try { f_120(); } catch (...) { throw; } }
-static void f_122() { try { f_121(); } catch (...) { throw; } }
-static void f_123() { try { f_122(); } catch (...) { throw; } }
-static void f_124() { try { f_123(); } catch (...) { throw; } }
-static void f_125() { try { f_124(); } catch (...) { throw; } }
-static void f_126() { try { f_125(); } catch (...) { throw; } }
-static void f_127() { try { f_126(); } catch (...) { throw; } }
-static void f_128() { try { f_127(); } catch (...) { throw; } }
-static void f_129() { try { f_128(); } catch (...) { throw; } }
-static void f_130() { try { f_129(); } catch (...) { throw; } }
-static void f_131() { try { f_130(); } catch (...) { throw; } }
-static void f_132() { try { f_131(); } catch (...) { throw; } }
-static void f_133() { try { f_132(); } catch (...) { throw; } }
-static void f_134() { try { f_133(); } catch (...) { throw; } }
-static void f_135() { try { f_134(); } catch (...) { throw; } }
-static void f_136() { try { f_135(); } catch (...) { throw; } }
-static void f_137() { try { f_136(); } catch (...) { throw; } }
-static void f_138() { try { f_137(); } catch (...) { throw; } }
-static void f_139() { try { f_138(); } catch (...) { throw; } }
-static void f_140() { try { f_139(); } catch (...) { throw; } }
-static void f_141() { try { f_140(); } catch (...) { throw; } }
-static void f_142() { try { f_141(); } catch (...) { throw; } }
-static void f_143() { try { f_142(); } catch (...) { throw; } }
-static void f_144() { try { f_143(); } catch (...) { throw; } }
-static void f_145() { try { f_144(); } catch (...) { throw; } }
-static void f_146() { try { f_145(); } catch (...) { throw; } }
-static void f_147() { try { f_146(); } catch (...) { throw; } }
-static void f_148() { try { f_147(); } catch (...) { throw; } }
-static void f_149() { try { f_148(); } catch (...) { throw; } }
-static void f_150() { try { f_149(); } catch (...) { throw; } }
-static void f_151() { try { f_150(); } catch (...) { throw; } }
-static void f_152() { try { f_151(); } catch (...) { throw; } }
-static void f_153() { try { f_152(); } catch (...) { throw; } }
-static void f_154() { try { f_153(); } catch (...) { throw; } }
-static void f_155() { try { f_154(); } catch (...) { throw; } }
-static void f_156() { try { f_155(); } catch (...) { throw; } }
-static void f_157() { try { f_156(); } catch (...) { throw; } }
-static void f_158() { try { f_157(); } catch (...) { throw; } }
-static void f_159() { try { f_158(); } catch (...) { throw; } }
-static void f_160() { try { f_159(); } catch (...) { throw; } }
-static void f_161() { try { f_160(); } catch (...) { throw; } }
-static void f_162() { try { f_161(); } catch (...) { throw; } }
-static void f_163() { try { f_162(); } catch (...) { throw; } }
-static void f_164() { try { f_163(); } catch (...) { throw; } }
-static void f_165() { try { f_164(); } catch (...) { throw; } }
-static void f_166() { try { f_165(); } catch (...) { throw; } }
-static void f_167() { try { f_166(); } catch (...) { throw; } }
-static void f_168() { try { f_167(); } catch (...) { throw; } }
-static void f_169() { try { f_168(); } catch (...) { throw; } }
-static void f_170() { try { f_169(); } catch (...) { throw; } }
-static void f_171() { try { f_170(); } catch (...) { throw; } }
-static void f_172() { try { f_171(); } catch (...) { throw; } }
-static void f_173() { try { f_172(); } catch (...) { throw; } }
-static void f_174() { try { f_173(); } catch (...) { throw; } }
-static void f_175() { try { f_174(); } catch (...) { throw; } }
-static void f_176() { try { f_175(); } catch (...) { throw; } }
-static void f_177() { try { f_176(); } catch (...) { throw; } }
-static void f_178() { try { f_177(); } catch (...) { throw; } }
-static void f_179() { try { f_178(); } catch (...) { throw; } }
-static void f_180() { try { f_179(); } catch (...) { throw; } }
-static void f_181() { try { f_180(); } catch (...) { throw; } }
-static void f_182() { try { f_181(); } catch (...) { throw; } }
-static void f_183() { try { f_182(); } catch (...) { throw; } }
-static void f_184() { try { f_183(); } catch (...) { throw; } }
-static void f_185() { try { f_184(); } catch (...) { throw; } }
-static void f_186() { try { f_185(); } catch (...) { throw; } }
-static void f_187() { try { f_186(); } catch (...) { throw; } }
-static void f_188() { try { f_187(); } catch (...) { throw; } }
-static void f_189() { try { f_188(); } catch (...) { throw; } }
-static void f_190() { try { f_189(); } catch (...) { throw; } }
-static void f_191() { try { f_190(); } catch (...) { throw; } }
-static void f_192() { try { f_191(); } catch (...) { throw; } }
-static void f_193() { try { f_192(); } catch (...) { throw; } }
-static void f_194() { try { f_193(); } catch (...) { throw; } }
-static void f_195() { try { f_194(); } catch (...) { throw; } }
-static void f_196() { try { f_195(); } catch (...) { throw; } }
-static void f_197() { try { f_196(); } catch (...) { throw; } }
-static void f_198() { try { f_197(); } catch (...) { throw; } }
-static void f_199() { try { f_198(); } catch (...) { throw; } }
-static void f_200() { try { f_199(); } catch (...) { throw; } }
-static void f_201() { try { f_200(); } catch (...) { throw; } }
-static void f_202() { try { f_201(); } catch (...) { throw; } }
-static void f_203() { try { f_202(); } catch (...) { throw; } }
-static void f_204() { try { f_203(); } catch (...) { throw; } }
-static void f_205() { try { f_204(); } catch (...) { throw; } }
-static void f_206() { try { f_205(); } catch (...) { throw; } }
-static void f_207() { try { f_206(); } catch (...) { throw; } }
-static void f_208() { try { f_207(); } catch (...) { throw; } }
-static void f_209() { try { f_208(); } catch (...) { throw; } }
-static void f_210() { try { f_209(); } catch (...) { throw; } }
-static void f_211() { try { f_210(); } catch (...) { throw; } }
-static void f_212() { try { f_211(); } catch (...) { throw; } }
-static void f_213() { try { f_212(); } catch (...) { throw; } }
-static void f_214() { try { f_213(); } catch (...) { throw; } }
-static void f_215() { try { f_214(); } catch (...) { throw; } }
-static void f_216() { try { f_215(); } catch (...) { throw; } }
-static void f_217() { try { f_216(); } catch (...) { throw; } }
-static void f_218() { try { f_217(); } catch (...) { throw; } }
-static void f_219() { try { f_218(); } catch (...) { throw; } }
-static void f_220() { try { f_219(); } catch (...) { throw; } }
-static void f_221() { try { f_220(); } catch (...) { throw; } }
-static void f_222() { try { f_221(); } catch (...) { throw; } }
-static void f_223() { try { f_222(); } catch (...) { throw; } }
-static void f_224() { try { f_223(); } catch (...) { throw; } }
-static void f_225() { try { f_224(); } catch (...) { throw; } }
-static void f_226() { try { f_225(); } catch (...) { throw; } }
-static void f_227() { try { f_226(); } catch (...) { throw; } }
-static void f_228() { try { f_227(); } catch (...) { throw; } }
-static void f_229() { try { f_228(); } catch (...) { throw; } }
-static void f_230() { try { f_229(); } catch (...) { throw; } }
-static void f_231() { try { f_230(); } catch (...) { throw; } }
-static void f_232() { try { f_231(); } catch (...) { throw; } }
-static void f_233() { try { f_232(); } catch (...) { throw; } }
-static void f_234() { try { f_233(); } catch (...) { throw; } }
-static void f_235() { try { f_234(); } catch (...) { throw; } }
-static void f_236() { try { f_235(); } catch (...) { throw; } }
-static void f_237() { try { f_236(); } catch (...) { throw; } }
-static void f_238() { try { f_237(); } catch (...) { throw; } }
-static void f_239() { try { f_238(); } catch (...) { throw; } }
-static void f_240() { try { f_239(); } catch (...) { throw; } }
-static void f_241() { try { f_240(); } catch (...) { throw; } }
-static void f_242() { try { f_241(); } catch (...) { throw; } }
-static void f_243() { try { f_242(); } catch (...) { throw; } }
-static void f_244() { try { f_243(); } catch (...) { throw; } }
-static void f_245() { try { f_244(); } catch (...) { throw; } }
-static void f_246() { try { f_245(); } catch (...) { throw; } }
-static void f_247() { try { f_246(); } catch (...) { throw; } }
-static void f_248() { try { f_247(); } catch (...) { throw; } }
-static void f_249() { try { f_248(); } catch (...) { throw; } }
-static void f_250() { try { f_249(); } catch (...) { throw; } }
-static void f_251() { try { f_250(); } catch (...) { throw; } }
-static void f_252() { try { f_251(); } catch (...) { throw; } }
-static void f_253() { try { f_252(); } catch (...) { throw; } }
-static void f_254() { try { f_253(); } catch (...) { throw; } }
-static void f_255() { try { f_254(); } catch (...) { throw; } }
-static void f_256() { try { f_255(); } catch (...) { throw; } }
-static void f_257() { try { f_256(); } catch (...) { throw; } }
-static void f_258() { try { f_257(); } catch (...) { throw; } }
-static void f_259() { try { f_258(); } catch (...) { throw; } }
-static void f_260() { try { f_259(); } catch (...) { throw; } }
-static void f_261() { try { f_260(); } catch (...) { throw; } }
-static void f_262() { try { f_261(); } catch (...) { throw; } }
-static void f_263() { try { f_262(); } catch (...) { throw; } }
-static void f_264() { try { f_263(); } catch (...) { throw; } }
-static void f_265() { try { f_264(); } catch (...) { throw; } }
-static void f_266() { try { f_265(); } catch (...) { throw; } }
-static void f_267() { try { f_266(); } catch (...) { throw; } }
-static void f_268() { try { f_267(); } catch (...) { throw; } }
-static void f_269() { try { f_268(); } catch (...) { throw; } }
-static void f_270() { try { f_269(); } catch (...) { throw; } }
-static void f_271() { try { f_270(); } catch (...) { throw; } }
-static void f_272() { try { f_271(); } catch (...) { throw; } }
-static void f_273() { try { f_272(); } catch (...) { throw; } }
-static void f_274() { try { f_273(); } catch (...) { throw; } }
-static void f_275() { try { f_274(); } catch (...) { throw; } }
-static void f_276() { try { f_275(); } catch (...) { throw; } }
-static void f_277() { try { f_276(); } catch (...) { throw; } }
-static void f_278() { try { f_277(); } catch (...) { throw; } }
-static void f_279() { try { f_278(); } catch (...) { throw; } }
-static void f_280() { try { f_279(); } catch (...) { throw; } }
-static void f_281() { try { f_280(); } catch (...) { throw; } }
-static void f_282() { try { f_281(); } catch (...) { throw; } }
-static void f_283() { try { f_282(); } catch (...) { throw; } }
-static void f_284() { try { f_283(); } catch (...) { throw; } }
-static void f_285() { try { f_284(); } catch (...) { throw; } }
-static void f_286() { try { f_285(); } catch (...) { throw; } }
-static void f_287() { try { f_286(); } catch (...) { throw; } }
-static void f_288() { try { f_287(); } catch (...) { throw; } }
-static void f_289() { try { f_288(); } catch (...) { throw; } }
-static void f_290() { try { f_289(); } catch (...) { throw; } }
-static void f_291() { try { f_290(); } catch (...) { throw; } }
-static void f_292() { try { f_291(); } catch (...) { throw; } }
-static void f_293() { try { f_292(); } catch (...) { throw; } }
-static void f_294() { try { f_293(); } catch (...) { throw; } }
-static void f_295() { try { f_294(); } catch (...) { throw; } }
-static void f_296() { try { f_295(); } catch (...) { throw; } }
-static void f_297() { try { f_296(); } catch (...) { throw; } }
-static void f_298() { try { f_297(); } catch (...) { throw; } }
-static void f_299() { try { f_298(); } catch (...) { throw; } }
-static void f_300() { try { f_299(); } catch (...) { throw; } }
-static void f_301() { try { f_300(); } catch (...) { throw; } }
-static void f_302() { try { f_301(); } catch (...) { throw; } }
-static void f_303() { try { f_302(); } catch (...) { throw; } }
-static void f_304() { try { f_303(); } catch (...) { throw; } }
-static void f_305() { try { f_304(); } catch (...) { throw; } }
-static void f_306() { try { f_305(); } catch (...) { throw; } }
-static void f_307() { try { f_306(); } catch (...) { throw; } }
-static void f_308() { try { f_307(); } catch (...) { throw; } }
-static void f_309() { try { f_308(); } catch (...) { throw; } }
-static void f_310() { try { f_309(); } catch (...) { throw; } }
-static void f_311() { try { f_310(); } catch (...) { throw; } }
-static void f_312() { try { f_311(); } catch (...) { throw; } }
-static void f_313() { try { f_312(); } catch (...) { throw; } }
-static void f_314() { try { f_313(); } catch (...) { throw; } }
-static void f_315() { try { f_314(); } catch (...) { throw; } }
-static void f_316() { try { f_315(); } catch (...) { throw; } }
-static void f_317() { try { f_316(); } catch (...) { throw; } }
-static void f_318() { try { f_317(); } catch (...) { throw; } }
-static void f_319() { try { f_318(); } catch (...) { throw; } }
-static void f_320() { try { f_319(); } catch (...) { throw; } }
-static void f_321() { try { f_320(); } catch (...) { throw; } }
-static void f_322() { try { f_321(); } catch (...) { throw; } }
-static void f_323() { try { f_322(); } catch (...) { throw; } }
-static void f_324() { try { f_323(); } catch (...) { throw; } }
-static void f_325() { try { f_324(); } catch (...) { throw; } }
-static void f_326() { try { f_325(); } catch (...) { throw; } }
-static void f_327() { try { f_326(); } catch (...) { throw; } }
-static void f_328() { try { f_327(); } catch (...) { throw; } }
-static void f_329() { try { f_328(); } catch (...) { throw; } }
-static void f_330() { try { f_329(); } catch (...) { throw; } }
-static void f_331() { try { f_330(); } catch (...) { throw; } }
-static void f_332() { try { f_331(); } catch (...) { throw; } }
-static void f_333() { try { f_332(); } catch (...) { throw; } }
-static void f_334() { try { f_333(); } catch (...) { throw; } }
-static void f_335() { try { f_334(); } catch (...) { throw; } }
-static void f_336() { try { f_335(); } catch (...) { throw; } }
-static void f_337() { try { f_336(); } catch (...) { throw; } }
-static void f_338() { try { f_337(); } catch (...) { throw; } }
-static void f_339() { try { f_338(); } catch (...) { throw; } }
-static void f_340() { try { f_339(); } catch (...) { throw; } }
-static void f_341() { try { f_340(); } catch (...) { throw; } }
-static void f_342() { try { f_341(); } catch (...) { throw; } }
-static void f_343() { try { f_342(); } catch (...) { throw; } }
-static void f_344() { try { f_343(); } catch (...) { throw; } }
-static void f_345() { try { f_344(); } catch (...) { throw; } }
-static void f_346() { try { f_345(); } catch (...) { throw; } }
-static void f_347() { try { f_346(); } catch (...) { throw; } }
-static void f_348() { try { f_347(); } catch (...) { throw; } }
-static void f_349() { try { f_348(); } catch (...) { throw; } }
-static void f_350() { try { f_349(); } catch (...) { throw; } }
-static void f_351() { try { f_350(); } catch (...) { throw; } }
-static void f_352() { try { f_351(); } catch (...) { throw; } }
-static void f_353() { try { f_352(); } catch (...) { throw; } }
-static void f_354() { try { f_353(); } catch (...) { throw; } }
-static void f_355() { try { f_354(); } catch (...) { throw; } }
-static void f_356() { try { f_355(); } catch (...) { throw; } }
-static void f_357() { try { f_356(); } catch (...) { throw; } }
-static void f_358() { try { f_357(); } catch (...) { throw; } }
-static void f_359() { try { f_358(); } catch (...) { throw; } }
-static void f_360() { try { f_359(); } catch (...) { throw; } }
-static void f_361() { try { f_360(); } catch (...) { throw; } }
-static void f_362() { try { f_361(); } catch (...) { throw; } }
-static void f_363() { try { f_362(); } catch (...) { throw; } }
-static void f_364() { try { f_363(); } catch (...) { throw; } }
-static void f_365() { try { f_364(); } catch (...) { throw; } }
-static void f_366() { try { f_365(); } catch (...) { throw; } }
-static void f_367() { try { f_366(); } catch (...) { throw; } }
-static void f_368() { try { f_367(); } catch (...) { throw; } }
-static void f_369() { try { f_368(); } catch (...) { throw; } }
-static void f_370() { try { f_369(); } catch (...) { throw; } }
-static void f_371() { try { f_370(); } catch (...) { throw; } }
-static void f_372() { try { f_371(); } catch (...) { throw; } }
-static void f_373() { try { f_372(); } catch (...) { throw; } }
-static void f_374() { try { f_373(); } catch (...) { throw; } }
-static void f_375() { try { f_374(); } catch (...) { throw; } }
-static void f_376() { try { f_375(); } catch (...) { throw; } }
-static void f_377() { try { f_376(); } catch (...) { throw; } }
-static void f_378() { try { f_377(); } catch (...) { throw; } }
-static void f_379() { try { f_378(); } catch (...) { throw; } }
-static void f_380() { try { f_379(); } catch (...) { throw; } }
-static void f_381() { try { f_380(); } catch (...) { throw; } }
-static void f_382() { try { f_381(); } catch (...) { throw; } }
-static void f_383() { try { f_382(); } catch (...) { throw; } }
-static void f_384() { try { f_383(); } catch (...) { throw; } }
-static void f_385() { try { f_384(); } catch (...) { throw; } }
-static void f_386() { try { f_385(); } catch (...) { throw; } }
-static void f_387() { try { f_386(); } catch (...) { throw; } }
-static void f_388() { try { f_387(); } catch (...) { throw; } }
-static void f_389() { try { f_388(); } catch (...) { throw; } }
-static void f_390() { try { f_389(); } catch (...) { throw; } }
-static void f_391() { try { f_390(); } catch (...) { throw; } }
-static void f_392() { try { f_391(); } catch (...) { throw; } }
-static void f_393() { try { f_392(); } catch (...) { throw; } }
-static void f_394() { try { f_393(); } catch (...) { throw; } }
-static void f_395() { try { f_394(); } catch (...) { throw; } }
-static void f_396() { try { f_395(); } catch (...) { throw; } }
-static void f_397() { try { f_396(); } catch (...) { throw; } }
-static void f_398() { try { f_397(); } catch (...) { throw; } }
-static void f_399() { try { f_398(); } catch (...) { throw; } }
-static void f_400() { try { f_399(); } catch (...) { throw; } }
-static void f_401() { try { f_400(); } catch (...) { throw; } }
-static void f_402() { try { f_401(); } catch (...) { throw; } }
-static void f_403() { try { f_402(); } catch (...) { throw; } }
-static void f_404() { try { f_403(); } catch (...) { throw; } }
-static void f_405() { try { f_404(); } catch (...) { throw; } }
-static void f_406() { try { f_405(); } catch (...) { throw; } }
-static void f_407() { try { f_406(); } catch (...) { throw; } }
-static void f_408() { try { f_407(); } catch (...) { throw; } }
-static void f_409() { try { f_408(); } catch (...) { throw; } }
-static void f_410() { try { f_409(); } catch (...) { throw; } }
-static void f_411() { try { f_410(); } catch (...) { throw; } }
-static void f_412() { try { f_411(); } catch (...) { throw; } }
-static void f_413() { try { f_412(); } catch (...) { throw; } }
-static void f_414() { try { f_413(); } catch (...) { throw; } }
-static void f_415() { try { f_414(); } catch (...) { throw; } }
-static void f_416() { try { f_415(); } catch (...) { throw; } }
-static void f_417() { try { f_416(); } catch (...) { throw; } }
-static void f_418() { try { f_417(); } catch (...) { throw; } }
-static void f_419() { try { f_418(); } catch (...) { throw; } }
-static void f_420() { try { f_419(); } catch (...) { throw; } }
-static void f_421() { try { f_420(); } catch (...) { throw; } }
-static void f_422() { try { f_421(); } catch (...) { throw; } }
-static void f_423() { try { f_422(); } catch (...) { throw; } }
-static void f_424() { try { f_423(); } catch (...) { throw; } }
-static void f_425() { try { f_424(); } catch (...) { throw; } }
-static void f_426() { try { f_425(); } catch (...) { throw; } }
-static void f_427() { try { f_426(); } catch (...) { throw; } }
-static void f_428() { try { f_427(); } catch (...) { throw; } }
-static void f_429() { try { f_428(); } catch (...) { throw; } }
-static void f_430() { try { f_429(); } catch (...) { throw; } }
-static void f_431() { try { f_430(); } catch (...) { throw; } }
-static void f_432() { try { f_431(); } catch (...) { throw; } }
-static void f_433() { try { f_432(); } catch (...) { throw; } }
-static void f_434() { try { f_433(); } catch (...) { throw; } }
-static void f_435() { try { f_434(); } catch (...) { throw; } }
-static void f_436() { try { f_435(); } catch (...) { throw; } }
-static void f_437() { try { f_436(); } catch (...) { throw; } }
-static void f_438() { try { f_437(); } catch (...) { throw; } }
-static void f_439() { try { f_438(); } catch (...) { throw; } }
-static void f_440() { try { f_439(); } catch (...) { throw; } }
-static void f_441() { try { f_440(); } catch (...) { throw; } }
-static void f_442() { try { f_441(); } catch (...) { throw; } }
-static void f_443() { try { f_442(); } catch (...) { throw; } }
-static void f_444() { try { f_443(); } catch (...) { throw; } }
-static void f_445() { try { f_444(); } catch (...) { throw; } }
-static void f_446() { try { f_445(); } catch (...) { throw; } }
-static void f_447() { try { f_446(); } catch (...) { throw; } }
-static void f_448() { try { f_447(); } catch (...) { throw; } }
-static void f_449() { try { f_448(); } catch (...) { throw; } }
-static void f_450() { try { f_449(); } catch (...) { throw; } }
-static void f_451() { try { f_450(); } catch (...) { throw; } }
-static void f_452() { try { f_451(); } catch (...) { throw; } }
-static void f_453() { try { f_452(); } catch (...) { throw; } }
-static void f_454() { try { f_453(); } catch (...) { throw; } }
-static void f_455() { try { f_454(); } catch (...) { throw; } }
-static void f_456() { try { f_455(); } catch (...) { throw; } }
-static void f_457() { try { f_456(); } catch (...) { throw; } }
-static void f_458() { try { f_457(); } catch (...) { throw; } }
-static void f_459() { try { f_458(); } catch (...) { throw; } }
-static void f_460() { try { f_459(); } catch (...) { throw; } }
-static void f_461() { try { f_460(); } catch (...) { throw; } }
-static void f_462() { try { f_461(); } catch (...) { throw; } }
-static void f_463() { try { f_462(); } catch (...) { throw; } }
-static void f_464() { try { f_463(); } catch (...) { throw; } }
-static void f_465() { try { f_464(); } catch (...) { throw; } }
-static void f_466() { try { f_465(); } catch (...) { throw; } }
-static void f_467() { try { f_466(); } catch (...) { throw; } }
-static void f_468() { try { f_467(); } catch (...) { throw; } }
-static void f_469() { try { f_468(); } catch (...) { throw; } }
-static void f_470() { try { f_469(); } catch (...) { throw; } }
-static void f_471() { try { f_470(); } catch (...) { throw; } }
-static void f_472() { try { f_471(); } catch (...) { throw; } }
-static void f_473() { try { f_472(); } catch (...) { throw; } }
-static void f_474() { try { f_473(); } catch (...) { throw; } }
-static void f_475() { try { f_474(); } catch (...) { throw; } }
-static void f_476() { try { f_475(); } catch (...) { throw; } }
-static void f_477() { try { f_476(); } catch (...) { throw; } }
-static void f_478() { try { f_477(); } catch (...) { throw; } }
-static void f_479() { try { f_478(); } catch (...) { throw; } }
-static void f_480() { try { f_479(); } catch (...) { throw; } }
-static void f_481() { try { f_480(); } catch (...) { throw; } }
-static void f_482() { try { f_481(); } catch (...) { throw; } }
-static void f_483() { try { f_482(); } catch (...) { throw; } }
-static void f_484() { try { f_483(); } catch (...) { throw; } }
-static void f_485() { try { f_484(); } catch (...) { throw; } }
-static void f_486() { try { f_485(); } catch (...) { throw; } }
-static void f_487() { try { f_486(); } catch (...) { throw; } }
-static void f_488() { try { f_487(); } catch (...) { throw; } }
-static void f_489() { try { f_488(); } catch (...) { throw; } }
-static void f_490() { try { f_489(); } catch (...) { throw; } }
-static void f_491() { try { f_490(); } catch (...) { throw; } }
-static void f_492() { try { f_491(); } catch (...) { throw; } }
-static void f_493() { try { f_492(); } catch (...) { throw; } }
-static void f_494() { try { f_493(); } catch (...) { throw; } }
-static void f_495() { try { f_494(); } catch (...) { throw; } }
-static void f_496() { try { f_495(); } catch (...) { throw; } }
-static void f_497() { try { f_496(); } catch (...) { throw; } }
-static void f_498() { try { f_497(); } catch (...) { throw; } }
-static void f_499() { try { f_498(); } catch (...) { throw; } }
-static void f_500() { try { f_499(); } catch (...) { throw; } }
-static void f_501() { try { f_500(); } catch (...) { throw; } }
-static void f_502() { try { f_501(); } catch (...) { throw; } }
-static void f_503() { try { f_502(); } catch (...) { throw; } }
-static void f_504() { try { f_503(); } catch (...) { throw; } }
-static void f_505() { try { f_504(); } catch (...) { throw; } }
-static void f_506() { try { f_505(); } catch (...) { throw; } }
-static void f_507() { try { f_506(); } catch (...) { throw; } }
-static void f_508() { try { f_507(); } catch (...) { throw; } }
-static void f_509() { try { f_508(); } catch (...) { throw; } }
-static void f_510() { try { f_509(); } catch (...) { throw; } }
-static void f_511() { try { f_510(); } catch (...) { throw; } }
-static void f_512() { try { f_511(); } catch (...) { throw; } }
-static void f_513() { try { f_512(); } catch (...) { throw; } }
-static void f_514() { try { f_513(); } catch (...) { throw; } }
-static void f_515() { try { f_514(); } catch (...) { throw; } }
-static void f_516() { try { f_515(); } catch (...) { throw; } }
-static void f_517() { try { f_516(); } catch (...) { throw; } }
-static void f_518() { try { f_517(); } catch (...) { throw; } }
-static void f_519() { try { f_518(); } catch (...) { throw; } }
-static void f_520() { try { f_519(); } catch (...) { throw; } }
-static void f_521() { try { f_520(); } catch (...) { throw; } }
-static void f_522() { try { f_521(); } catch (...) { throw; } }
-static void f_523() { try { f_522(); } catch (...) { throw; } }
-static void f_524() { try { f_523(); } catch (...) { throw; } }
-static void f_525() { try { f_524(); } catch (...) { throw; } }
-static void f_526() { try { f_525(); } catch (...) { throw; } }
-static void f_527() { try { f_526(); } catch (...) { throw; } }
-static void f_528() { try { f_527(); } catch (...) { throw; } }
-static void f_529() { try { f_528(); } catch (...) { throw; } }
-static void f_530() { try { f_529(); } catch (...) { throw; } }
-static void f_531() { try { f_530(); } catch (...) { throw; } }
-static void f_532() { try { f_531(); } catch (...) { throw; } }
-static void f_533() { try { f_532(); } catch (...) { throw; } }
-static void f_534() { try { f_533(); } catch (...) { throw; } }
-static void f_535() { try { f_534(); } catch (...) { throw; } }
-static void f_536() { try { f_535(); } catch (...) { throw; } }
-static void f_537() { try { f_536(); } catch (...) { throw; } }
-static void f_538() { try { f_537(); } catch (...) { throw; } }
-static void f_539() { try { f_538(); } catch (...) { throw; } }
-static void f_540() { try { f_539(); } catch (...) { throw; } }
-static void f_541() { try { f_540(); } catch (...) { throw; } }
-static void f_542() { try { f_541(); } catch (...) { throw; } }
-static void f_543() { try { f_542(); } catch (...) { throw; } }
-static void f_544() { try { f_543(); } catch (...) { throw; } }
-static void f_545() { try { f_544(); } catch (...) { throw; } }
-static void f_546() { try { f_545(); } catch (...) { throw; } }
-static void f_547() { try { f_546(); } catch (...) { throw; } }
-static void f_548() { try { f_547(); } catch (...) { throw; } }
-static void f_549() { try { f_548(); } catch (...) { throw; } }
-static void f_550() { try { f_549(); } catch (...) { throw; } }
-static void f_551() { try { f_550(); } catch (...) { throw; } }
-static void f_552() { try { f_551(); } catch (...) { throw; } }
-static void f_553() { try { f_552(); } catch (...) { throw; } }
-static void f_554() { try { f_553(); } catch (...) { throw; } }
-static void f_555() { try { f_554(); } catch (...) { throw; } }
-static void f_556() { try { f_555(); } catch (...) { throw; } }
-static void f_557() { try { f_556(); } catch (...) { throw; } }
-static void f_558() { try { f_557(); } catch (...) { throw; } }
-static void f_559() { try { f_558(); } catch (...) { throw; } }
-static void f_560() { try { f_559(); } catch (...) { throw; } }
-static void f_561() { try { f_560(); } catch (...) { throw; } }
-static void f_562() { try { f_561(); } catch (...) { throw; } }
-static void f_563() { try { f_562(); } catch (...) { throw; } }
-static void f_564() { try { f_563(); } catch (...) { throw; } }
-static void f_565() { try { f_564(); } catch (...) { throw; } }
-static void f_566() { try { f_565(); } catch (...) { throw; } }
-static void f_567() { try { f_566(); } catch (...) { throw; } }
-static void f_568() { try { f_567(); } catch (...) { throw; } }
-static void f_569() { try { f_568(); } catch (...) { throw; } }
-static void f_570() { try { f_569(); } catch (...) { throw; } }
-static void f_571() { try { f_570(); } catch (...) { throw; } }
-static void f_572() { try { f_571(); } catch (...) { throw; } }
-static void f_573() { try { f_572(); } catch (...) { throw; } }
-static void f_574() { try { f_573(); } catch (...) { throw; } }
-static void f_575() { try { f_574(); } catch (...) { throw; } }
-static void f_576() { try { f_575(); } catch (...) { throw; } }
-static void f_577() { try { f_576(); } catch (...) { throw; } }
-static void f_578() { try { f_577(); } catch (...) { throw; } }
-static void f_579() { try { f_578(); } catch (...) { throw; } }
-static void f_580() { try { f_579(); } catch (...) { throw; } }
-static void f_581() { try { f_580(); } catch (...) { throw; } }
-static void f_582() { try { f_581(); } catch (...) { throw; } }
-static void f_583() { try { f_582(); } catch (...) { throw; } }
-static void f_584() { try { f_583(); } catch (...) { throw; } }
-static void f_585() { try { f_584(); } catch (...) { throw; } }
-static void f_586() { try { f_585(); } catch (...) { throw; } }
-static void f_587() { try { f_586(); } catch (...) { throw; } }
-static void f_588() { try { f_587(); } catch (...) { throw; } }
-static void f_589() { try { f_588(); } catch (...) { throw; } }
-static void f_590() { try { f_589(); } catch (...) { throw; } }
-static void f_591() { try { f_590(); } catch (...) { throw; } }
-static void f_592() { try { f_591(); } catch (...) { throw; } }
-static void f_593() { try { f_592(); } catch (...) { throw; } }
-static void f_594() { try { f_593(); } catch (...) { throw; } }
-static void f_595() { try { f_594(); } catch (...) { throw; } }
-static void f_596() { try { f_595(); } catch (...) { throw; } }
-static void f_597() { try { f_596(); } catch (...) { throw; } }
-static void f_598() { try { f_597(); } catch (...) { throw; } }
-static void f_599() { try { f_598(); } catch (...) { throw; } }
-static void f_600() { try { f_599(); } catch (...) { throw; } }
-static void f_601() { try { f_600(); } catch (...) { throw; } }
-static void f_602() { try { f_601(); } catch (...) { throw; } }
-static void f_603() { try { f_602(); } catch (...) { throw; } }
-static void f_604() { try { f_603(); } catch (...) { throw; } }
-static void f_605() { try { f_604(); } catch (...) { throw; } }
-static void f_606() { try { f_605(); } catch (...) { throw; } }
-static void f_607() { try { f_606(); } catch (...) { throw; } }
-static void f_608() { try { f_607(); } catch (...) { throw; } }
-static void f_609() { try { f_608(); } catch (...) { throw; } }
-static void f_610() { try { f_609(); } catch (...) { throw; } }
-static void f_611() { try { f_610(); } catch (...) { throw; } }
-static void f_612() { try { f_611(); } catch (...) { throw; } }
-static void f_613() { try { f_612(); } catch (...) { throw; } }
-static void f_614() { try { f_613(); } catch (...) { throw; } }
-static void f_615() { try { f_614(); } catch (...) { throw; } }
-static void f_616() { try { f_615(); } catch (...) { throw; } }
-static void f_617() { try { f_616(); } catch (...) { throw; } }
-static void f_618() { try { f_617(); } catch (...) { throw; } }
-static void f_619() { try { f_618(); } catch (...) { throw; } }
-static void f_620() { try { f_619(); } catch (...) { throw; } }
-static void f_621() { try { f_620(); } catch (...) { throw; } }
-static void f_622() { try { f_621(); } catch (...) { throw; } }
-static void f_623() { try { f_622(); } catch (...) { throw; } }
-static void f_624() { try { f_623(); } catch (...) { throw; } }
-static void f_625() { try { f_624(); } catch (...) { throw; } }
-static void f_626() { try { f_625(); } catch (...) { throw; } }
-static void f_627() { try { f_626(); } catch (...) { throw; } }
-static void f_628() { try { f_627(); } catch (...) { throw; } }
-static void f_629() { try { f_628(); } catch (...) { throw; } }
-static void f_630() { try { f_629(); } catch (...) { throw; } }
-static void f_631() { try { f_630(); } catch (...) { throw; } }
-static void f_632() { try { f_631(); } catch (...) { throw; } }
-static void f_633() { try { f_632(); } catch (...) { throw; } }
-static void f_634() { try { f_633(); } catch (...) { throw; } }
-static void f_635() { try { f_634(); } catch (...) { throw; } }
-static void f_636() { try { f_635(); } catch (...) { throw; } }
-static void f_637() { try { f_636(); } catch (...) { throw; } }
-static void f_638() { try { f_637(); } catch (...) { throw; } }
-static void f_639() { try { f_638(); } catch (...) { throw; } }
-static void f_640() { try { f_639(); } catch (...) { throw; } }
-static void f_641() { try { f_640(); } catch (...) { throw; } }
-static void f_642() { try { f_641(); } catch (...) { throw; } }
-static void f_643() { try { f_642(); } catch (...) { throw; } }
-static void f_644() { try { f_643(); } catch (...) { throw; } }
-static void f_645() { try { f_644(); } catch (...) { throw; } }
-static void f_646() { try { f_645(); } catch (...) { throw; } }
-static void f_647() { try { f_646(); } catch (...) { throw; } }
-static void f_648() { try { f_647(); } catch (...) { throw; } }
-static void f_649() { try { f_648(); } catch (...) { throw; } }
-static void f_650() { try { f_649(); } catch (...) { throw; } }
-static void f_651() { try { f_650(); } catch (...) { throw; } }
-static void f_652() { try { f_651(); } catch (...) { throw; } }
-static void f_653() { try { f_652(); } catch (...) { throw; } }
-static void f_654() { try { f_653(); } catch (...) { throw; } }
-static void f_655() { try { f_654(); } catch (...) { throw; } }
-static void f_656() { try { f_655(); } catch (...) { throw; } }
-static void f_657() { try { f_656(); } catch (...) { throw; } }
-static void f_658() { try { f_657(); } catch (...) { throw; } }
-static void f_659() { try { f_658(); } catch (...) { throw; } }
-static void f_660() { try { f_659(); } catch (...) { throw; } }
-static void f_661() { try { f_660(); } catch (...) { throw; } }
-static void f_662() { try { f_661(); } catch (...) { throw; } }
-static void f_663() { try { f_662(); } catch (...) { throw; } }
-static void f_664() { try { f_663(); } catch (...) { throw; } }
-static void f_665() { try { f_664(); } catch (...) { throw; } }
-static void f_666() { try { f_665(); } catch (...) { throw; } }
-static void f_667() { try { f_666(); } catch (...) { throw; } }
-static void f_668() { try { f_667(); } catch (...) { throw; } }
-static void f_669() { try { f_668(); } catch (...) { throw; } }
-static void f_670() { try { f_669(); } catch (...) { throw; } }
-static void f_671() { try { f_670(); } catch (...) { throw; } }
-static void f_672() { try { f_671(); } catch (...) { throw; } }
-static void f_673() { try { f_672(); } catch (...) { throw; } }
-static void f_674() { try { f_673(); } catch (...) { throw; } }
-static void f_675() { try { f_674(); } catch (...) { throw; } }
-static void f_676() { try { f_675(); } catch (...) { throw; } }
-static void f_677() { try { f_676(); } catch (...) { throw; } }
-static void f_678() { try { f_677(); } catch (...) { throw; } }
-static void f_679() { try { f_678(); } catch (...) { throw; } }
-static void f_680() { try { f_679(); } catch (...) { throw; } }
-static void f_681() { try { f_680(); } catch (...) { throw; } }
-static void f_682() { try { f_681(); } catch (...) { throw; } }
-static void f_683() { try { f_682(); } catch (...) { throw; } }
-static void f_684() { try { f_683(); } catch (...) { throw; } }
-static void f_685() { try { f_684(); } catch (...) { throw; } }
-static void f_686() { try { f_685(); } catch (...) { throw; } }
-static void f_687() { try { f_686(); } catch (...) { throw; } }
-static void f_688() { try { f_687(); } catch (...) { throw; } }
-static void f_689() { try { f_688(); } catch (...) { throw; } }
-static void f_690() { try { f_689(); } catch (...) { throw; } }
-static void f_691() { try { f_690(); } catch (...) { throw; } }
-static void f_692() { try { f_691(); } catch (...) { throw; } }
-static void f_693() { try { f_692(); } catch (...) { throw; } }
-static void f_694() { try { f_693(); } catch (...) { throw; } }
-static void f_695() { try { f_694(); } catch (...) { throw; } }
-static void f_696() { try { f_695(); } catch (...) { throw; } }
-static void f_697() { try { f_696(); } catch (...) { throw; } }
-static void f_698() { try { f_697(); } catch (...) { throw; } }
-static void f_699() { try { f_698(); } catch (...) { throw; } }
-static void f_700() { try { f_699(); } catch (...) { throw; } }
-static void f_701() { try { f_700(); } catch (...) { throw; } }
-static void f_702() { try { f_701(); } catch (...) { throw; } }
-static void f_703() { try { f_702(); } catch (...) { throw; } }
-static void f_704() { try { f_703(); } catch (...) { throw; } }
-static void f_705() { try { f_704(); } catch (...) { throw; } }
-static void f_706() { try { f_705(); } catch (...) { throw; } }
-static void f_707() { try { f_706(); } catch (...) { throw; } }
-static void f_708() { try { f_707(); } catch (...) { throw; } }
-static void f_709() { try { f_708(); } catch (...) { throw; } }
-static void f_710() { try { f_709(); } catch (...) { throw; } }
-static void f_711() { try { f_710(); } catch (...) { throw; } }
-static void f_712() { try { f_711(); } catch (...) { throw; } }
-static void f_713() { try { f_712(); } catch (...) { throw; } }
-static void f_714() { try { f_713(); } catch (...) { throw; } }
-static void f_715() { try { f_714(); } catch (...) { throw; } }
-static void f_716() { try { f_715(); } catch (...) { throw; } }
-static void f_717() { try { f_716(); } catch (...) { throw; } }
-static void f_718() { try { f_717(); } catch (...) { throw; } }
-static void f_719() { try { f_718(); } catch (...) { throw; } }
-static void f_720() { try { f_719(); } catch (...) { throw; } }
-static void f_721() { try { f_720(); } catch (...) { throw; } }
-static void f_722() { try { f_721(); } catch (...) { throw; } }
-static void f_723() { try { f_722(); } catch (...) { throw; } }
-static void f_724() { try { f_723(); } catch (...) { throw; } }
-static void f_725() { try { f_724(); } catch (...) { throw; } }
-static void f_726() { try { f_725(); } catch (...) { throw; } }
-static void f_727() { try { f_726(); } catch (...) { throw; } }
-static void f_728() { try { f_727(); } catch (...) { throw; } }
-static void f_729() { try { f_728(); } catch (...) { throw; } }
-static void f_730() { try { f_729(); } catch (...) { throw; } }
-static void f_731() { try { f_730(); } catch (...) { throw; } }
-static void f_732() { try { f_731(); } catch (...) { throw; } }
-static void f_733() { try { f_732(); } catch (...) { throw; } }
-static void f_734() { try { f_733(); } catch (...) { throw; } }
-static void f_735() { try { f_734(); } catch (...) { throw; } }
-static void f_736() { try { f_735(); } catch (...) { throw; } }
-static void f_737() { try { f_736(); } catch (...) { throw; } }
-static void f_738() { try { f_737(); } catch (...) { throw; } }
-static void f_739() { try { f_738(); } catch (...) { throw; } }
-static void f_740() { try { f_739(); } catch (...) { throw; } }
-static void f_741() { try { f_740(); } catch (...) { throw; } }
-static void f_742() { try { f_741(); } catch (...) { throw; } }
-static void f_743() { try { f_742(); } catch (...) { throw; } }
-static void f_744() { try { f_743(); } catch (...) { throw; } }
-static void f_745() { try { f_744(); } catch (...) { throw; } }
-static void f_746() { try { f_745(); } catch (...) { throw; } }
-static void f_747() { try { f_746(); } catch (...) { throw; } }
-static void f_748() { try { f_747(); } catch (...) { throw; } }
-static void f_749() { try { f_748(); } catch (...) { throw; } }
-static void f_750() { try { f_749(); } catch (...) { throw; } }
-static void f_751() { try { f_750(); } catch (...) { throw; } }
-static void f_752() { try { f_751(); } catch (...) { throw; } }
-static void f_753() { try { f_752(); } catch (...) { throw; } }
-static void f_754() { try { f_753(); } catch (...) { throw; } }
-static void f_755() { try { f_754(); } catch (...) { throw; } }
-static void f_756() { try { f_755(); } catch (...) { throw; } }
-static void f_757() { try { f_756(); } catch (...) { throw; } }
-static void f_758() { try { f_757(); } catch (...) { throw; } }
-static void f_759() { try { f_758(); } catch (...) { throw; } }
-static void f_760() { try { f_759(); } catch (...) { throw; } }
-static void f_761() { try { f_760(); } catch (...) { throw; } }
-static void f_762() { try { f_761(); } catch (...) { throw; } }
-static void f_763() { try { f_762(); } catch (...) { throw; } }
-static void f_764() { try { f_763(); } catch (...) { throw; } }
-static void f_765() { try { f_764(); } catch (...) { throw; } }
-static void f_766() { try { f_765(); } catch (...) { throw; } }
-static void f_767() { try { f_766(); } catch (...) { throw; } }
-static void f_768() { try { f_767(); } catch (...) { throw; } }
-static void f_769() { try { f_768(); } catch (...) { throw; } }
-static void f_770() { try { f_769(); } catch (...) { throw; } }
-static void f_771() { try { f_770(); } catch (...) { throw; } }
-static void f_772() { try { f_771(); } catch (...) { throw; } }
-static void f_773() { try { f_772(); } catch (...) { throw; } }
-static void f_774() { try { f_773(); } catch (...) { throw; } }
-static void f_775() { try { f_774(); } catch (...) { throw; } }
-static void f_776() { try { f_775(); } catch (...) { throw; } }
-static void f_777() { try { f_776(); } catch (...) { throw; } }
-static void f_778() { try { f_777(); } catch (...) { throw; } }
-static void f_779() { try { f_778(); } catch (...) { throw; } }
-static void f_780() { try { f_779(); } catch (...) { throw; } }
-static void f_781() { try { f_780(); } catch (...) { throw; } }
-static void f_782() { try { f_781(); } catch (...) { throw; } }
-static void f_783() { try { f_782(); } catch (...) { throw; } }
-static void f_784() { try { f_783(); } catch (...) { throw; } }
-static void f_785() { try { f_784(); } catch (...) { throw; } }
-static void f_786() { try { f_785(); } catch (...) { throw; } }
-static void f_787() { try { f_786(); } catch (...) { throw; } }
-static void f_788() { try { f_787(); } catch (...) { throw; } }
-static void f_789() { try { f_788(); } catch (...) { throw; } }
-static void f_790() { try { f_789(); } catch (...) { throw; } }
-static void f_791() { try { f_790(); } catch (...) { throw; } }
-static void f_792() { try { f_791(); } catch (...) { throw; } }
-static void f_793() { try { f_792(); } catch (...) { throw; } }
-static void f_794() { try { f_793(); } catch (...) { throw; } }
-static void f_795() { try { f_794(); } catch (...) { throw; } }
-static void f_796() { try { f_795(); } catch (...) { throw; } }
-static void f_797() { try { f_796(); } catch (...) { throw; } }
-static void f_798() { try { f_797(); } catch (...) { throw; } }
-static void f_799() { try { f_798(); } catch (...) { throw; } }
-static void f_800() { try { f_799(); } catch (...) { throw; } }
-static void f_801() { try { f_800(); } catch (...) { throw; } }
-static void f_802() { try { f_801(); } catch (...) { throw; } }
-static void f_803() { try { f_802(); } catch (...) { throw; } }
-static void f_804() { try { f_803(); } catch (...) { throw; } }
-static void f_805() { try { f_804(); } catch (...) { throw; } }
-static void f_806() { try { f_805(); } catch (...) { throw; } }
-static void f_807() { try { f_806(); } catch (...) { throw; } }
-static void f_808() { try { f_807(); } catch (...) { throw; } }
-static void f_809() { try { f_808(); } catch (...) { throw; } }
-static void f_810() { try { f_809(); } catch (...) { throw; } }
-static void f_811() { try { f_810(); } catch (...) { throw; } }
-static void f_812() { try { f_811(); } catch (...) { throw; } }
-static void f_813() { try { f_812(); } catch (...) { throw; } }
-static void f_814() { try { f_813(); } catch (...) { throw; } }
-static void f_815() { try { f_814(); } catch (...) { throw; } }
-static void f_816() { try { f_815(); } catch (...) { throw; } }
-static void f_817() { try { f_816(); } catch (...) { throw; } }
-static void f_818() { try { f_817(); } catch (...) { throw; } }
-static void f_819() { try { f_818(); } catch (...) { throw; } }
-static void f_820() { try { f_819(); } catch (...) { throw; } }
-static void f_821() { try { f_820(); } catch (...) { throw; } }
-static void f_822() { try { f_821(); } catch (...) { throw; } }
-static void f_823() { try { f_822(); } catch (...) { throw; } }
-static void f_824() { try { f_823(); } catch (...) { throw; } }
-static void f_825() { try { f_824(); } catch (...) { throw; } }
-static void f_826() { try { f_825(); } catch (...) { throw; } }
-static void f_827() { try { f_826(); } catch (...) { throw; } }
-static void f_828() { try { f_827(); } catch (...) { throw; } }
-static void f_829() { try { f_828(); } catch (...) { throw; } }
-static void f_830() { try { f_829(); } catch (...) { throw; } }
-static void f_831() { try { f_830(); } catch (...) { throw; } }
-static void f_832() { try { f_831(); } catch (...) { throw; } }
-static void f_833() { try { f_832(); } catch (...) { throw; } }
-static void f_834() { try { f_833(); } catch (...) { throw; } }
-static void f_835() { try { f_834(); } catch (...) { throw; } }
-static void f_836() { try { f_835(); } catch (...) { throw; } }
-static void f_837() { try { f_836(); } catch (...) { throw; } }
-static void f_838() { try { f_837(); } catch (...) { throw; } }
-static void f_839() { try { f_838(); } catch (...) { throw; } }
-static void f_840() { try { f_839(); } catch (...) { throw; } }
-static void f_841() { try { f_840(); } catch (...) { throw; } }
-static void f_842() { try { f_841(); } catch (...) { throw; } }
-static void f_843() { try { f_842(); } catch (...) { throw; } }
-static void f_844() { try { f_843(); } catch (...) { throw; } }
-static void f_845() { try { f_844(); } catch (...) { throw; } }
-static void f_846() { try { f_845(); } catch (...) { throw; } }
-static void f_847() { try { f_846(); } catch (...) { throw; } }
-static void f_848() { try { f_847(); } catch (...) { throw; } }
-static void f_849() { try { f_848(); } catch (...) { throw; } }
-static void f_850() { try { f_849(); } catch (...) { throw; } }
-static void f_851() { try { f_850(); } catch (...) { throw; } }
-static void f_852() { try { f_851(); } catch (...) { throw; } }
-static void f_853() { try { f_852(); } catch (...) { throw; } }
-static void f_854() { try { f_853(); } catch (...) { throw; } }
-static void f_855() { try { f_854(); } catch (...) { throw; } }
-static void f_856() { try { f_855(); } catch (...) { throw; } }
-static void f_857() { try { f_856(); } catch (...) { throw; } }
-static void f_858() { try { f_857(); } catch (...) { throw; } }
-static void f_859() { try { f_858(); } catch (...) { throw; } }
-static void f_860() { try { f_859(); } catch (...) { throw; } }
-static void f_861() { try { f_860(); } catch (...) { throw; } }
-static void f_862() { try { f_861(); } catch (...) { throw; } }
-static void f_863() { try { f_862(); } catch (...) { throw; } }
-static void f_864() { try { f_863(); } catch (...) { throw; } }
-static void f_865() { try { f_864(); } catch (...) { throw; } }
-static void f_866() { try { f_865(); } catch (...) { throw; } }
-static void f_867() { try { f_866(); } catch (...) { throw; } }
-static void f_868() { try { f_867(); } catch (...) { throw; } }
-static void f_869() { try { f_868(); } catch (...) { throw; } }
-static void f_870() { try { f_869(); } catch (...) { throw; } }
-static void f_871() { try { f_870(); } catch (...) { throw; } }
-static void f_872() { try { f_871(); } catch (...) { throw; } }
-static void f_873() { try { f_872(); } catch (...) { throw; } }
-static void f_874() { try { f_873(); } catch (...) { throw; } }
-static void f_875() { try { f_874(); } catch (...) { throw; } }
-static void f_876() { try { f_875(); } catch (...) { throw; } }
-static void f_877() { try { f_876(); } catch (...) { throw; } }
-static void f_878() { try { f_877(); } catch (...) { throw; } }
-static void f_879() { try { f_878(); } catch (...) { throw; } }
-static void f_880() { try { f_879(); } catch (...) { throw; } }
-static void f_881() { try { f_880(); } catch (...) { throw; } }
-static void f_882() { try { f_881(); } catch (...) { throw; } }
-static void f_883() { try { f_882(); } catch (...) { throw; } }
-static void f_884() { try { f_883(); } catch (...) { throw; } }
-static void f_885() { try { f_884(); } catch (...) { throw; } }
-static void f_886() { try { f_885(); } catch (...) { throw; } }
-static void f_887() { try { f_886(); } catch (...) { throw; } }
-static void f_888() { try { f_887(); } catch (...) { throw; } }
-static void f_889() { try { f_888(); } catch (...) { throw; } }
-static void f_890() { try { f_889(); } catch (...) { throw; } }
-static void f_891() { try { f_890(); } catch (...) { throw; } }
-static void f_892() { try { f_891(); } catch (...) { throw; } }
-static void f_893() { try { f_892(); } catch (...) { throw; } }
-static void f_894() { try { f_893(); } catch (...) { throw; } }
-static void f_895() { try { f_894(); } catch (...) { throw; } }
-static void f_896() { try { f_895(); } catch (...) { throw; } }
-static void f_897() { try { f_896(); } catch (...) { throw; } }
-static void f_898() { try { f_897(); } catch (...) { throw; } }
-static void f_899() { try { f_898(); } catch (...) { throw; } }
-static void f_900() { try { f_899(); } catch (...) { throw; } }
-static void f_901() { try { f_900(); } catch (...) { throw; } }
-static void f_902() { try { f_901(); } catch (...) { throw; } }
-static void f_903() { try { f_902(); } catch (...) { throw; } }
-static void f_904() { try { f_903(); } catch (...) { throw; } }
-static void f_905() { try { f_904(); } catch (...) { throw; } }
-static void f_906() { try { f_905(); } catch (...) { throw; } }
-static void f_907() { try { f_906(); } catch (...) { throw; } }
-static void f_908() { try { f_907(); } catch (...) { throw; } }
-static void f_909() { try { f_908(); } catch (...) { throw; } }
-static void f_910() { try { f_909(); } catch (...) { throw; } }
-static void f_911() { try { f_910(); } catch (...) { throw; } }
-static void f_912() { try { f_911(); } catch (...) { throw; } }
-static void f_913() { try { f_912(); } catch (...) { throw; } }
-static void f_914() { try { f_913(); } catch (...) { throw; } }
-static void f_915() { try { f_914(); } catch (...) { throw; } }
-static void f_916() { try { f_915(); } catch (...) { throw; } }
-static void f_917() { try { f_916(); } catch (...) { throw; } }
-static void f_918() { try { f_917(); } catch (...) { throw; } }
-static void f_919() { try { f_918(); } catch (...) { throw; } }
-static void f_920() { try { f_919(); } catch (...) { throw; } }
-static void f_921() { try { f_920(); } catch (...) { throw; } }
-static void f_922() { try { f_921(); } catch (...) { throw; } }
-static void f_923() { try { f_922(); } catch (...) { throw; } }
-static void f_924() { try { f_923(); } catch (...) { throw; } }
-static void f_925() { try { f_924(); } catch (...) { throw; } }
-static void f_926() { try { f_925(); } catch (...) { throw; } }
-static void f_927() { try { f_926(); } catch (...) { throw; } }
-static void f_928() { try { f_927(); } catch (...) { throw; } }
-static void f_929() { try { f_928(); } catch (...) { throw; } }
-static void f_930() { try { f_929(); } catch (...) { throw; } }
-static void f_931() { try { f_930(); } catch (...) { throw; } }
-static void f_932() { try { f_931(); } catch (...) { throw; } }
-static void f_933() { try { f_932(); } catch (...) { throw; } }
-static void f_934() { try { f_933(); } catch (...) { throw; } }
-static void f_935() { try { f_934(); } catch (...) { throw; } }
-static void f_936() { try { f_935(); } catch (...) { throw; } }
-static void f_937() { try { f_936(); } catch (...) { throw; } }
-static void f_938() { try { f_937(); } catch (...) { throw; } }
-static void f_939() { try { f_938(); } catch (...) { throw; } }
-static void f_940() { try { f_939(); } catch (...) { throw; } }
-static void f_941() { try { f_940(); } catch (...) { throw; } }
-static void f_942() { try { f_941(); } catch (...) { throw; } }
-static void f_943() { try { f_942(); } catch (...) { throw; } }
-static void f_944() { try { f_943(); } catch (...) { throw; } }
-static void f_945() { try { f_944(); } catch (...) { throw; } }
-static void f_946() { try { f_945(); } catch (...) { throw; } }
-static void f_947() { try { f_946(); } catch (...) { throw; } }
-static void f_948() { try { f_947(); } catch (...) { throw; } }
-static void f_949() { try { f_948(); } catch (...) { throw; } }
-static void f_950() { try { f_949(); } catch (...) { throw; } }
-static void f_951() { try { f_950(); } catch (...) { throw; } }
-static void f_952() { try { f_951(); } catch (...) { throw; } }
-static void f_953() { try { f_952(); } catch (...) { throw; } }
-static void f_954() { try { f_953(); } catch (...) { throw; } }
-static void f_955() { try { f_954(); } catch (...) { throw; } }
-static void f_956() { try { f_955(); } catch (...) { throw; } }
-static void f_957() { try { f_956(); } catch (...) { throw; } }
-static void f_958() { try { f_957(); } catch (...) { throw; } }
-static void f_959() { try { f_958(); } catch (...) { throw; } }
-static void f_960() { try { f_959(); } catch (...) { throw; } }
-static void f_961() { try { f_960(); } catch (...) { throw; } }
-static void f_962() { try { f_961(); } catch (...) { throw; } }
-static void f_963() { try { f_962(); } catch (...) { throw; } }
-static void f_964() { try { f_963(); } catch (...) { throw; } }
-static void f_965() { try { f_964(); } catch (...) { throw; } }
-static void f_966() { try { f_965(); } catch (...) { throw; } }
-static void f_967() { try { f_966(); } catch (...) { throw; } }
-static void f_968() { try { f_967(); } catch (...) { throw; } }
-static void f_969() { try { f_968(); } catch (...) { throw; } }
-static void f_970() { try { f_969(); } catch (...) { throw; } }
-static void f_971() { try { f_970(); } catch (...) { throw; } }
-static void f_972() { try { f_971(); } catch (...) { throw; } }
-static void f_973() { try { f_972(); } catch (...) { throw; } }
-static void f_974() { try { f_973(); } catch (...) { throw; } }
-static void f_975() { try { f_974(); } catch (...) { throw; } }
-static void f_976() { try { f_975(); } catch (...) { throw; } }
-static void f_977() { try { f_976(); } catch (...) { throw; } }
-static void f_978() { try { f_977(); } catch (...) { throw; } }
-static void f_979() { try { f_978(); } catch (...) { throw; } }
-static void f_980() { try { f_979(); } catch (...) { throw; } }
-static void f_981() { try { f_980(); } catch (...) { throw; } }
-static void f_982() { try { f_981(); } catch (...) { throw; } }
-static void f_983() { try { f_982(); } catch (...) { throw; } }
-static void f_984() { try { f_983(); } catch (...) { throw; } }
-static void f_985() { try { f_984(); } catch (...) { throw; } }
-static void f_986() { try { f_985(); } catch (...) { throw; } }
-static void f_987() { try { f_986(); } catch (...) { throw; } }
-static void f_988() { try { f_987(); } catch (...) { throw; } }
-static void f_989() { try { f_988(); } catch (...) { throw; } }
-static void f_990() { try { f_989(); } catch (...) { throw; } }
-static void f_991() { try { f_990(); } catch (...) { throw; } }
-static void f_992() { try { f_991(); } catch (...) { throw; } }
-static void f_993() { try { f_992(); } catch (...) { throw; } }
-static void f_994() { try { f_993(); } catch (...) { throw; } }
-static void f_995() { try { f_994(); } catch (...) { throw; } }
-static void f_996() { try { f_995(); } catch (...) { throw; } }
-static void f_997() { try { f_996(); } catch (...) { throw; } }
-static void f_998() { try { f_997(); } catch (...) { throw; } }
-static void f_999() { try { f_998(); } catch (...) { throw; } }
-static void f_1000() { try { f_999(); } catch (...) { throw; } }
-static void f_1001() { try { f_1000(); } catch (...) { throw; } }
-static void f_1002() { try { f_1001(); } catch (...) { throw; } }
-static void f_1003() { try { f_1002(); } catch (...) { throw; } }
-static void f_1004() { try { f_1003(); } catch (...) { throw; } }
-static void f_1005() { try { f_1004(); } catch (...) { throw; } }
-static void f_1006() { try { f_1005(); } catch (...) { throw; } }
-static void f_1007() { try { f_1006(); } catch (...) { throw; } }
-static void f_1008() { try { f_1007(); } catch (...) { throw; } }
-static void f_1009() { try { f_1008(); } catch (...) { throw; } }
-static void f_1010() { try { f_1009(); } catch (...) { throw; } }
-static void f_1011() { try { f_1010(); } catch (...) { throw; } }
-static void f_1012() { try { f_1011(); } catch (...) { throw; } }
-static void f_1013() { try { f_1012(); } catch (...) { throw; } }
-static void f_1014() { try { f_1013(); } catch (...) { throw; } }
-static void f_1015() { try { f_1014(); } catch (...) { throw; } }
-static void f_1016() { try { f_1015(); } catch (...) { throw; } }
-static void f_1017() { try { f_1016(); } catch (...) { throw; } }
-static void f_1018() { try { f_1017(); } catch (...) { throw; } }
-static void f_1019() { try { f_1018(); } catch (...) { throw; } }
-static void f_1020() { try { f_1019(); } catch (...) { throw; } }
+template <int N>
+void f() { try { f<N - 1>(); } catch (...) { throw; } }
+
+template <>
+void f<0>() { throw 42; }
+
int main(int argc, char *argv[]) {
try {
- f_1020();
+ f<1020>();
} catch (int n) {
return 42 - n;
}
More information about the llvm-branch-commits
mailing list