From 43723a189c0f01a3d91f8cfe642ba694549ed37c Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 4 Dec 2018 01:41:32 -0500 Subject: [PATCH] Future-proof the ARM64 ABI by not reserving the entire top byte. Targets that want to use armv8.5a memory tagging will need this. Hopefully nobody comes up with a brilliant reason they need to use anything else. --- stdlib/public/SwiftShims/System.h | 5 ++- test/IRGen/bridge_object_arm64.sil | 4 +- test/IRGen/enum_top_bits_reserved.sil | 58 +++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 test/IRGen/enum_top_bits_reserved.sil diff --git a/stdlib/public/SwiftShims/System.h b/stdlib/public/SwiftShims/System.h index a8fae1f724f96..e7d4df2d5f13c 100644 --- a/stdlib/public/SwiftShims/System.h +++ b/stdlib/public/SwiftShims/System.h @@ -136,9 +136,10 @@ /// Darwin reserves the low 4GB of address space. #define SWIFT_ABI_DARWIN_ARM64_LEAST_VALID_POINTER 0x100000000ULL -// TBI guarantees the top byte of pointers is unused. +// TBI guarantees the top byte of pointers is unused, but ARMv8.5-A +// claims the bottom four bits of that for memory tagging. // Heap objects are eight-byte aligned. -#define SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK 0xFF00000000000007ULL +#define SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK 0xF000000000000007ULL // Objective-C reserves just the high bit for tagged pointers. #define SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK 0x8000000000000000ULL diff --git a/test/IRGen/bridge_object_arm64.sil b/test/IRGen/bridge_object_arm64.sil index 053cee1e8ae07..3642d702a0ada 100644 --- a/test/IRGen/bridge_object_arm64.sil +++ b/test/IRGen/bridge_object_arm64.sil @@ -35,8 +35,8 @@ entry(%c : $C, %w : $Builtin.Word): // CHECK: [[TAGGED_RESULT:%.*]] = bitcast [[BRIDGE]] %0 to [[C:%objc_object\*]] // CHECK: br label %tagged-cont // CHECK: not-tagged-pointer: -// -- 0x00ff_ffff_ffff_fff8 -// CHECK: [[MASKED_BITS:%.*]] = and i64 [[BOBITS]], 72057594037927928 +// -- 0x0fff_ffff_ffff_fff8 +// CHECK: [[MASKED_BITS:%.*]] = and i64 [[BOBITS]], 1152921504606846968 // CHECK: [[MASKED_RESULT:%.*]] = inttoptr i64 [[MASKED_BITS]] to [[C]] // CHECK: br label %tagged-cont // CHECK: tagged-cont: diff --git a/test/IRGen/enum_top_bits_reserved.sil b/test/IRGen/enum_top_bits_reserved.sil new file mode 100644 index 0000000000000..d65470278328a --- /dev/null +++ b/test/IRGen/enum_top_bits_reserved.sil @@ -0,0 +1,58 @@ +// RUN: %swift -module-name test -emit-ir -target arm64-apple-ios10.0 %s | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-arm64 +// RUN: %swift -module-name test -emit-ir -target x86_64-apple-macosx10.12 %s | %FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-x86_64 + +class NativeClass {} +sil_vtable NativeClass {} + +// On 64-bit targets, there are 3 spare bits in the alignment bits and +// either 4 (arm64) or 8 (everywhere else) spare bits in the high byte. +// Consume those bits one by one. + +enum A { + case either(NativeClass) + case or(NativeClass) +} + +enum B { + case either(A) + case or(A) +} + +enum C { + case either(B) + case or(B) +} + +enum D { + case either(C) + case or(C) +} + +enum E { + case either(D) + case or(D) +} + +enum F { + case either(E) + case or(E) +} + +enum G { + case either(F) + case or(F) +} + +// Okay, we've claimed 7 spare bits. On ARM64, the eighth spare bit will +// require an extra discriminator. + +// CHECK-LABEL: @"$s4test1HOWV" = internal constant %swift.enum_vwtable +// CHECK-x86_64-SAME: i64 8, +// CHECK-x86_64-SAME: i64 8, +// CHECK-arm64-SAME: i64 9, +// CHECK-arm64-SAME: i64 16, + +enum H { + case either(G) + case or(G) +}