Reland "Add gen_snapshot binaries, producing Linux ARM64/x64 snapshots"
This is a reland of commit e6d55c6c2f6193a7ec5ab7aaae0c25eaebd620b9
Reworks guards for 64-bit Windows unwinding support code so that
it is not included in any 64-bit Windows gen_snapshot executable that
targets a non-64-bit Windows platform.
TEST=ci, build only
Original change's description:
> Add gen_snapshot binaries, producing Linux ARM64/x64 snapshots
>
> Inspired by `//runtime/bin:gen_snapshot_fuchsia`, required for go/dart-cross-compile.
>
> TEST=ci, build only
>
> Change-Id: Ie521c984a8f44d25f3f78d946af9416582a572dc
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/410402
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com>
Change-Id: I4f1323ac8f7ab215c2dffeef188f70c466fb62ea
Cq-Include-Trybots: luci.dart.try:vm-win-release-arm64-try,vm-win-release-ia32-try,vm-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/413402
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ivan Inozemtsev <iinozemtsev@google.com>
Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com>
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 450411e..f60f6be 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -128,6 +128,26 @@
defines = [ "DART_TARGET_OS_FUCHSIA" ]
}
+# We need to build gen_snapshot targeting Linux ARM64 during a build
+# of the SDK. This configuration is used to unconditionally target
+# Linux ARM64. It should not be combined with dart_os_config and dart_arch_config.
+config("dart_linux_arm64_config") {
+ defines = [
+ "DART_TARGET_OS_LINUX",
+ "TARGET_ARCH_ARM64",
+ ]
+}
+
+# We need to build gen_snapshot targeting Linux ARM64 during a build
+# of the SDK. This configuration is used to unconditionally target
+# Linux ARM64. It should not be combined with dart_os_config and dart_arch_config.
+config("dart_linux_x64_config") {
+ defines = [
+ "DART_TARGET_OS_LINUX",
+ "TARGET_ARCH_X64",
+ ]
+}
+
config("dart_arch_config") {
defines = []
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index b3a1350..6b53a0b 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -107,6 +107,20 @@
extra_configs = [ "..:dart_product_config" ]
}
+build_libdart_builtin("libdart_builtin_product_linux_x64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_x64_config",
+ ]
+}
+
+build_libdart_builtin("libdart_builtin_product_linux_arm64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_arm64_config",
+ ]
+}
+
template("build_native_assets_api") {
extra_configs = []
if (defined(invoker.extra_configs)) {
@@ -330,6 +344,31 @@
]
}
+build_gen_snapshot("gen_snapshot_product_linux_x64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_x64_config",
+ ]
+ extra_deps = [
+ ":gen_snapshot_dart_io_product_linux_x64",
+ ":libdart_builtin_product_linux_x64",
+ "..:libdart_precompiler_product_linux_x64",
+ "../platform:libdart_platform_precompiler_product_linux_x64",
+ ]
+}
+
+build_gen_snapshot("gen_snapshot_product_linux_arm64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_arm64_config",
+ ]
+ extra_deps = [
+ ":gen_snapshot_dart_io_product_linux_arm64",
+ ":libdart_builtin_product_linux_arm64",
+ "..:libdart_precompiler_product_linux_arm64",
+ "../platform:libdart_platform_precompiler_product_linux_arm64",
+ ]
+}
build_gen_snapshot("gen_snapshot_host_targeting_host") {
extra_configs = [ "..:dart_maybe_product_config" ]
extra_deps = [
@@ -434,6 +473,20 @@
]
}
+build_gen_snapshot_dart_io("gen_snapshot_dart_io_product_linux_x64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_x64_config",
+ ]
+}
+
+build_gen_snapshot_dart_io("gen_snapshot_dart_io_product_linux_arm64") {
+ extra_configs = [
+ "..:dart_product_config",
+ "..:dart_linux_arm64_config",
+ ]
+}
+
# A source set for the implementation of 'dart:io' library.
template("dart_io") {
extra_configs = []
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index 70baa9c..6c8b656 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -241,8 +241,7 @@
const dart::elf::Symbol* dynamic_symbol_table_ = nullptr;
uword dynamic_symbol_count_ = 0;
-#if defined(DART_HOST_OS_WINDOWS) && \
- (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
+#if defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT)
// Dynamic table for looking up unwinding exceptions info.
// Initialized by LoadSegments as we load executable segment.
MallocGrowableArray<void*> dynamic_runtime_function_tables_;
@@ -295,8 +294,7 @@
}
LoadedElf::~LoadedElf() {
-#if defined(DART_HOST_OS_WINDOWS) && \
- (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
+#if defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT)
for (intptr_t i = 0; i < dynamic_runtime_function_tables_.length(); i++) {
UnwindingRecordsPlatform::UnregisterDynamicTable(
dynamic_runtime_function_tables_[i]);
@@ -465,8 +463,7 @@
CHECK_ERROR(memory != nullptr, "Could not map segment.");
CHECK_ERROR(memory->address() == memory_start,
"Mapping not at requested address.");
-#if defined(DART_HOST_OS_WINDOWS) && \
- (defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64))
+#if defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT)
// For executable pages register unwinding information that should be
// present on the page.
if (map_type == File::kReadExecute) {
diff --git a/runtime/configs.gni b/runtime/configs.gni
index c8ef631..c4b1dd1 100644
--- a/runtime/configs.gni
+++ b/runtime/configs.gni
@@ -63,6 +63,18 @@
_precompiler_product_host_targeting_host_config =
_base_host_targeting_host_config + _precompiler_base + _product
+_precompiler_product_linux_x64_config =
+ [
+ "$_dart_runtime:dart_config",
+ "$_dart_runtime:dart_linux_x64_config",
+ ] + _product + _precompiler_base
+
+_precompiler_product_linux_arm64_config =
+ [
+ "$_dart_runtime:dart_config",
+ "$_dart_runtime:dart_linux_arm64_config",
+ ] + _product + _precompiler_base
+
_all_configs = [
{
suffix = "_jit"
@@ -148,6 +160,20 @@
compiler = true
is_product = false
},
+ {
+ suffix = "_precompiler_product_linux_x64"
+ configs = _precompiler_product_linux_x64_config
+ snapshot = false
+ compiler = true
+ is_product = true
+ },
+ {
+ suffix = "_precompiler_product_linux_arm64"
+ configs = _precompiler_product_linux_arm64_config
+ snapshot = false
+ compiler = true
+ is_product = true
+ },
]
# This template creates a target for each of the configurations listed above.
diff --git a/runtime/platform/unwinding_records.cc b/runtime/platform/unwinding_records.cc
index e6e69d0..835464e 100644
--- a/runtime/platform/unwinding_records.cc
+++ b/runtime/platform/unwinding_records.cc
@@ -7,17 +7,19 @@
namespace dart {
-#if (!defined(DART_TARGET_OS_WINDOWS) && !defined(DART_HOST_OS_WINDOWS)) || \
- (!defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64))
+#if !(defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT) || \
+ defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT))
intptr_t UnwindingRecordsPlatform::SizeInBytes() {
return 0;
}
-#endif // (!defined(DART_TARGET_OS_WINDOWS) && !defined(DART_HOST_OS_WINDOWS))
+#endif // !defined(DART_TARGET_OS_WINDOWS) && !defined(DART_HOST_OS_WINDOWS)
-#if !defined(DART_HOST_OS_WINDOWS) || \
- (!defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64))
+// Also use empty definitions when running gen_snapshot on 64-bit Windows, as it
+// does not use the ELF loader, which is the client of these methods.
+#if !defined(DART_HOST_OS_WINDOWS) || !defined(ARCH_IS_64_BIT) || \
+ (defined(DART_PRECOMPILER) && !defined(TESTING))
void UnwindingRecordsPlatform::RegisterExecutableMemory(
void* start,
@@ -25,6 +27,6 @@
void** pp_dynamic_table) {}
void UnwindingRecordsPlatform::UnregisterDynamicTable(void* p_dynamic_table) {}
-#endif // !defined(DART_HOST_OS_WINDOWS) ...
+#endif // !defined(DART_HOST_OS_WINDOWS) || ...
} // namespace dart
diff --git a/runtime/platform/unwinding_records.h b/runtime/platform/unwinding_records.h
index 83d242a..0da447b 100644
--- a/runtime/platform/unwinding_records.h
+++ b/runtime/platform/unwinding_records.h
@@ -20,10 +20,25 @@
static void UnregisterDynamicTable(void* p_dynamic_table);
};
-#if (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS)) && \
- defined(TARGET_ARCH_X64)
+// These definitions are only needed if targeting 64-bit Windows, or if the
+// ELF loader may be used on 64-bit Windows.
+//
+// More specifically, a 64-bit Windows gen_snapshot that does not target
+// 64-bit Windows does not need these definitions, as the generated snapshot
+// should not contain Windows-specific unwinding records and gen_snapshot
+// does not uses the ELF loader.
+#if (defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)) || \
+ (defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT) && \
+ (!defined(DART_PRECOMPILER) || defined(TESTING)))
#pragma pack(push, 1)
+
+#if !defined(DART_HOST_OS_WINDOWS) || !defined(HOST_ARCH_X64)
+typedef uint32_t ULONG;
+typedef uint32_t DWORD;
+#endif
+
+#if defined(TARGET_ARCH_X64)
//
// Refer to https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64
//
@@ -49,7 +64,6 @@
} UNWIND_INFO, *PUNWIND_INFO;
#if !defined(DART_HOST_OS_WINDOWS)
-typedef uint32_t ULONG;
typedef struct _RUNTIME_FUNCTION {
ULONG BeginAddress;
ULONG EndAddress;
@@ -97,12 +111,7 @@
RUNTIME_FUNCTION runtime_function[1];
};
-#pragma pack(pop)
-
-#elif defined(TARGET_ARCH_ARM64) && \
- (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS))
-
-#pragma pack(push, 1)
+#elif defined(TARGET_ARCH_ARM64)
// ARM64 unwind codes are defined in below doc.
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
@@ -139,12 +148,9 @@
uint32_t CodeWords : 5;
};
-#if !defined(DART_HOST_OS_WINDOWS)
-typedef uint32_t ULONG;
-typedef uint32_t DWORD;
+#if !defined(DART_HOST_OS_WINDOWS) || !defined(HOST_ARCH_ARM64)
typedef struct _RUNTIME_FUNCTION {
ULONG BeginAddress;
- ULONG EndAddress;
ULONG UnwindData;
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
#endif
@@ -231,9 +237,13 @@
RUNTIME_FUNCTION runtime_function[kDefaultRuntimeFunctionCount];
};
+#else
+#error Unhandled Windows architecture.
+#endif
+
#pragma pack(pop)
-#endif // (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS))
+#endif // (defined(DART_TARGET_OS_WINDOWS) || ...
} // namespace dart
diff --git a/runtime/platform/unwinding_records_win.cc b/runtime/platform/unwinding_records_win.cc
index 937cd1d..6f9c6dc 100644
--- a/runtime/platform/unwinding_records_win.cc
+++ b/runtime/platform/unwinding_records_win.cc
@@ -9,23 +9,27 @@
namespace dart {
-#if (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS)) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+#if (defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)) || \
+ (defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT))
#if defined(TARGET_ARCH_X64)
const intptr_t kReservedUnwindingRecordsSizeBytes = 64;
-#else
+#elif defined(TARGET_ARCH_ARM64)
const intptr_t kReservedUnwindingRecordsSizeBytes = 4 * KB;
+#else
+#error Unhandled Windows architecture.
#endif
intptr_t UnwindingRecordsPlatform::SizeInBytes() {
return kReservedUnwindingRecordsSizeBytes;
}
-#endif // defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS)
+#endif // defined(DART_TARGET_OS_WINDOWS) ...
-#if defined(DART_HOST_OS_WINDOWS) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+// Only use these definitions when the ELF loader may be used on 64-bit Windows,
+// as it is the only client of these methods (e.g., _not_ in gen_snapshot).
+#if defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT) && \
+ (!defined(DART_PRECOMPILER) || defined(TESTING))
void UnwindingRecordsPlatform::RegisterExecutableMemory(
void* start,
@@ -54,6 +58,6 @@
RtlDeleteGrowableFunctionTable(p_dynamic_table);
}
-#endif // defined(DART_HOST_OS_WINDOWS)
+#endif // defined(DART_HOST_OS_WINDOWS) ...
} // namespace dart
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index acf0d72..0cea903 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -1430,8 +1430,7 @@
// No text section added means no .eh_frame.
if (text_section == nullptr) return;
-#if defined(DART_TARGET_OS_WINDOWS) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+#if defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)
// Append Windows unwinding instructions to the end of .text section.
{ // NOLINT
auto* const unwinding_instructions_frame = new (zone_) TextSection(type_);
@@ -1493,8 +1492,7 @@
// Emit an FDE covering each .text section.
for (const auto& portion : text_section->portions()) {
-#if defined(DART_TARGET_OS_WINDOWS) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+#if defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)
if (portion.label == 0) {
// Unwinding instructions sections doesn't have label, doesn't dwarf
continue;
diff --git a/runtime/vm/unwinding_records.cc b/runtime/vm/unwinding_records.cc
index 13109d6..e442118 100644
--- a/runtime/vm/unwinding_records.cc
+++ b/runtime/vm/unwinding_records.cc
@@ -7,22 +7,23 @@
namespace dart {
-#if (!defined(DART_TARGET_OS_WINDOWS) && !defined(DART_HOST_OS_WINDOWS)) || \
- (!defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64))
+#if !defined(DART_TARGET_OS_WINDOWS) || !defined(TARGET_ARCH_IS_64_BIT)
const void* UnwindingRecords::GenerateRecordsInto(intptr_t offset,
uint8_t* target_buffer) {
return nullptr;
}
-#endif
+#endif // !defined(DART_TARGET_OS_WINDOWS)
-#if !defined(DART_HOST_OS_WINDOWS) || \
- (!defined(TARGET_ARCH_X64) && !defined(TARGET_ARCH_ARM64))
+// Also use empty definitions when running gen_snapshot on 64-bit Windows, as
+// it does not use the ELF loader, which is the client of these methods.
+#if !defined(DART_HOST_OS_WINDOWS) || !defined(ARCH_IS_64_BIT) || \
+ (defined(DART_PRECOMPILER) && !defined(TESTING))
void UnwindingRecords::RegisterExecutablePage(Page* page) {}
void UnwindingRecords::UnregisterExecutablePage(Page* page) {}
-#endif
+#endif // !defined(DART_HOST_OS_WINDOWS)
} // namespace dart
diff --git a/runtime/vm/unwinding_records_win.cc b/runtime/vm/unwinding_records_win.cc
index a92c293..01e5410 100644
--- a/runtime/vm/unwinding_records_win.cc
+++ b/runtime/vm/unwinding_records_win.cc
@@ -10,8 +10,11 @@
namespace dart {
-#if (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS)) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+// When the host is 64-bit Windows but the target is not, only define this
+// when the ELF loader may be used, so _not_ in gen_snapshot.
+#if (defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)) || \
+ (defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT) && \
+ (!defined(DART_PRECOMPILER) || defined(TESTING)))
static void InitUnwindingRecord(intptr_t offset,
CodeRangeUnwindingRecord* record,
@@ -88,11 +91,15 @@
// cover it, more pages will need to reserved for unwind data.
ASSERT(remaining_size_in_bytes <= 0);
#else
-#error What architecture?
+#error Unhandled Windows architecture.
#endif
record->magic = kUnwindingRecordMagic;
}
+#endif // defined(DART_TARGET_OS_WINDOWS) || ...
+
+#if defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)
+
const void* UnwindingRecords::GenerateRecordsInto(intptr_t offset,
uint8_t* target_buffer) {
CodeRangeUnwindingRecord* record =
@@ -101,10 +108,13 @@
return target_buffer;
}
-#endif // (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS))
+#endif // defined(DART_TARGET_OS_WINDOWS) && defined(TARGET_ARCH_IS_64_BIT)
-#if defined(DART_HOST_OS_WINDOWS) && \
- (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64))
+// Only use these definitions when the ELF loader may be used on 64-bit
+// Windows, as it is the only client of these methods (e.g., _not_ in
+// gen_snapshot).
+#if defined(DART_HOST_OS_WINDOWS) && defined(ARCH_IS_64_BIT) && \
+ (!defined(DART_PRECOMPILER) || defined(TESTING))
// Special exception-unwinding records are put at the end of executable
// page on Windows for 64-bit applications.
@@ -144,6 +154,6 @@
RtlDeleteGrowableFunctionTable(record->dynamic_table);
}
-#endif // defined(DART_HOST_OS_WINDOWS)
+#endif // defined(DART_HOST_OS_WINDOWS) ...
} // namespace dart
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index fb7179c..cd014e3 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -855,6 +855,16 @@
public_deps += [ ":copy_wasm_opt" ]
}
}
+
+ if (dart_target_arch != "ia32" && dart_target_arch != "x86" &&
+ dart_target_arch != "arm") {
+ # Do not include gen_snapshot binaries for cross-compilation into
+ # SDK, but add them as a dependency, so that they are built.
+ public_deps += [
+ "../runtime/bin:gen_snapshot_product_linux_arm64",
+ "../runtime/bin:gen_snapshot_product_linux_x64",
+ ]
+ }
}
# Build a SDK with less stuff. It excludes dart2js, ddc, and web libraries.