111 lines
5.4 KiB
Plaintext
111 lines
5.4 KiB
Plaintext
From 7b2256f97b59192046eab312838f467def880605
|
|
Date: Sun, 9 Jan 2022 21:45:13 +0530
|
|
Subject: [PATCH] [android] Move the string and other tags in pointers to the
|
|
second byte because Android enabled memory tagging
|
|
|
|
Starting with Android 11, AArch64 placed a tag in the top byte of pointers to
|
|
allocations, which has been slowly rolling out to more devices and collides
|
|
with Swift's tags. Moving these tags to the second byte works around this
|
|
problem.
|
|
---
|
|
lib/IRGen/MetadataRequest.cpp | 28 ++++++++++--
|
|
lib/IRGen/SwiftTargetInfo.cpp | 15 +++++--
|
|
stdlib/public/SwiftShims/System.h | 9 ++++
|
|
|
|
diff --git a/swift/lib/IRGen/MetadataRequest.cpp b/swift/lib/IRGen/MetadataRequest.cpp
|
|
index 370b5bab779e2..d96e7b0d0f576 100644
|
|
--- a/swift/lib/IRGen/MetadataRequest.cpp
|
|
+++ b/swift/lib/IRGen/MetadataRequest.cpp
|
|
@@ -2681,9 +2681,16 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
|
|
unsigned mangledStringSize;
|
|
std::tie(mangledString, mangledStringSize) =
|
|
IGM.getTypeRef(type, CanGenericSignature(), MangledTypeRefRole::Metadata);
|
|
-
|
|
- assert(mangledStringSize < 0x80000000u
|
|
- && "2GB of mangled name ought to be enough for anyone");
|
|
+
|
|
+ // Android AArch64 reserves the top byte of the address for memory tagging
|
|
+ // since Android 11, so only use the bottom 23 bits to store this size
|
|
+ // and the 24th bit to signal that there is a size.
|
|
+ if (IGM.Triple.isAndroid() && IGM.Triple.getArch() == llvm::Triple::aarch64)
|
|
+ assert(mangledStringSize < 0x00800001u &&
|
|
+ "8MB of mangled name ought to be enough for Android AArch64");
|
|
+ else
|
|
+ assert(mangledStringSize < 0x80000000u &&
|
|
+ "2GB of mangled name ought to be enough for anyone");
|
|
|
|
// Get or create the cache variable if necessary.
|
|
auto cache = IGM.getAddrOfTypeMetadataDemanglingCacheVariable(type,
|
|
@@ -2753,6 +2760,21 @@ emitMetadataAccessByMangledName(IRGenFunction &IGF, CanType type,
|
|
auto contBB = subIGF.createBasicBlock("");
|
|
llvm::Value *comparison = subIGF.Builder.CreateICmpSLT(load,
|
|
llvm::ConstantInt::get(IGM.Int64Ty, 0));
|
|
+
|
|
+ // Check if the 24th bit is set on Android AArch64 and only instantiate the
|
|
+ // type metadata if it is, as otherwise it might be negative only because
|
|
+ // of the memory tag on Android.
|
|
+ if (IGM.Triple.isAndroid() &&
|
|
+ IGM.Triple.getArch() == llvm::Triple::aarch64) {
|
|
+
|
|
+ auto getBitAfterAndroidTag = subIGF.Builder.CreateAnd(
|
|
+ load, llvm::ConstantInt::get(IGM.Int64Ty, 0x0080000000000000));
|
|
+ auto checkNotAndroidTag = subIGF.Builder.CreateICmpNE(
|
|
+ getBitAfterAndroidTag, llvm::ConstantInt::get(IGM.Int64Ty, 0));
|
|
+
|
|
+ comparison = subIGF.Builder.CreateAnd(comparison, checkNotAndroidTag);
|
|
+ }
|
|
+
|
|
comparison = subIGF.Builder.CreateExpect(comparison,
|
|
llvm::ConstantInt::get(IGM.Int1Ty, 0));
|
|
subIGF.Builder.CreateCondBr(comparison, isUnfilledBB, contBB);
|
|
diff --git a/swift/lib/IRGen/SwiftTargetInfo.cpp b/swift/lib/IRGen/SwiftTargetInfo.cpp
|
|
index 97b70d6d75c0a..b2b2e70d3434e 100644
|
|
--- a/swift/lib/IRGen/SwiftTargetInfo.cpp
|
|
+++ b/swift/lib/IRGen/SwiftTargetInfo.cpp
|
|
@@ -36,10 +36,17 @@ static void setToMask(SpareBitVector &bits, unsigned size, uint64_t mask) {
|
|
/// Configures target-specific information for arm64 platforms.
|
|
static void configureARM64(IRGenModule &IGM, const llvm::Triple &triple,
|
|
SwiftTargetInfo &target) {
|
|
- setToMask(target.PointerSpareBits, 64,
|
|
- SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK);
|
|
- setToMask(target.ObjCPointerReservedBits, 64,
|
|
- SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK);
|
|
+ if (triple.isAndroid()) {
|
|
+ setToMask(target.PointerSpareBits, 64,
|
|
+ SWIFT_ABI_ANDROID_ARM64_SWIFT_SPARE_BITS_MASK);
|
|
+ setToMask(target.ObjCPointerReservedBits, 64,
|
|
+ SWIFT_ABI_ANDROID_ARM64_OBJC_RESERVED_BITS_MASK);
|
|
+ } else {
|
|
+ setToMask(target.PointerSpareBits, 64,
|
|
+ SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK);
|
|
+ setToMask(target.ObjCPointerReservedBits, 64,
|
|
+ SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK);
|
|
+ }
|
|
setToMask(target.IsObjCPointerBit, 64, SWIFT_ABI_ARM64_IS_OBJC_BIT);
|
|
|
|
if (triple.isOSDarwin()) {
|
|
diff --git a/swift/stdlib/public/SwiftShims/System.h b/swift/stdlib/public/SwiftShims/System.h
|
|
index 978ec41f1eafb..7ec3961fa0fc3 100644
|
|
--- a/swift/stdlib/public/SwiftShims/System.h
|
|
+++ b/swift/stdlib/public/SwiftShims/System.h
|
|
@@ -152,10 +152,19 @@
|
|
/// Darwin reserves the low 4GB of address space.
|
|
#define SWIFT_ABI_DARWIN_ARM64_LEAST_VALID_POINTER 0x100000000ULL
|
|
|
|
+// Android AArch64 reserves the top byte for pointer tagging since Android 11,
|
|
+// so shift the spare bits tag to the second byte and zero the ObjC tag.
|
|
+#define SWIFT_ABI_ANDROID_ARM64_SWIFT_SPARE_BITS_MASK 0x00F0000000000007ULL
|
|
+#define SWIFT_ABI_ANDROID_ARM64_OBJC_RESERVED_BITS_MASK 0x0000000000000000ULL
|
|
+
|
|
+#if defined(__ANDROID__) && defined(__aarch64__)
|
|
+#define SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK SWIFT_ABI_ANDROID_ARM64_SWIFT_SPARE_BITS_MASK
|
|
+#else
|
|
// 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 0xF000000000000007ULL
|
|
+#endif
|
|
|
|
// Objective-C reserves just the high bit for tagged pointers.
|
|
#define SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK 0x8000000000000000ULL
|