Skip to content

Support key paths on 32-bit platforms. #9214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions include/swift/ABI/HeapObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===--- HeapObject.h - ABI constants for heap objects -----------*- C++ *-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Constants used in the layout of heap objects.
//
//===----------------------------------------------------------------------===//

#ifndef __SWIFT_ABI_HEAPOBJECT_H__
#define __SWIFT_ABI_HEAPOBJECT_H__

#include "../../../stdlib/public/SwiftShims/HeapObject.h"

#endif // __SWIFT_ABI_HEAPOBJECT_H__
35 changes: 25 additions & 10 deletions lib/IRGen/GenKeyPath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/TypeLowering.h"
#include "swift/ABI/KeyPath.h"
#include "swift/ABI/HeapObject.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsIRGen.h"
Expand All @@ -42,15 +43,6 @@ using namespace irgen;
llvm::Constant *
IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
SILLocation diagLoc) {
// TODO: Landing 32-bit key paths requires some runtime changes to get the
// 8-byte object header.
if (getPointerSize() != Size(8)) {
Context.Diags.diagnose(diagLoc.getSourceLoc(),
diag::not_implemented,
"32-bit key paths");
return llvm::UndefValue::get(Int8PtrTy);
}

// See if we already emitted this.
auto found = KeyPathPatterns.find(pattern);
if (found != KeyPathPatterns.end())
Expand Down Expand Up @@ -119,13 +111,36 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
fields.setPacked(true);
// Add a zero-initialized header we can use for lazy initialization.
fields.add(llvm::ConstantInt::get(SizeTy, 0));


#ifndef NDEBUG
auto startOfObject = fields.getNextOffsetFromGlobal();
#endif

// Store references to metadata generator functions to generate the metadata
// for the root and leaf. These sit in the "isa" and object header parts of
// the final object.
fields.add(emitMetadataGenerator(rootTy));
fields.add(emitMetadataGenerator(valueTy));

// TODO: 32-bit still has a padding word
if (SizeTy == Int32Ty) {
fields.addInt32(0);
}

#ifndef NDEBUG
auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
unsigned expectedObjectHeaderSize;
if (SizeTy == Int64Ty)
expectedObjectHeaderSize = SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64;
else if (SizeTy == Int32Ty)
expectedObjectHeaderSize = SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32;
else
llvm_unreachable("unexpected pointer size");
assert((endOfObjectHeader - startOfObject).getValue()
== expectedObjectHeaderSize
&& "key path pattern header size doesn't match heap object header size");
#endif

// Add a pointer to the ObjC KVC compatibility string, if there is one, or
// null otherwise.
llvm::Constant *objcString;
Expand Down
8 changes: 8 additions & 0 deletions stdlib/public/SwiftShims/GlobalObjects.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ SWIFT_RUNTIME_STDLIB_INTERFACE
__swift_uint64_t _swift_stdlib_HashingDetail_fixedSeedOverride;

#ifdef __cplusplus

static_assert(std::is_pod<_SwiftEmptyArrayStorage>::value,
"empty array type should be POD");
static_assert(std::is_pod<_SwiftEmptyDictionaryStorage>::value,
"empty dictionary type should be POD");
static_assert(std::is_pod<_SwiftEmptySetStorage>::value,
"empty set type should be POD");

}} // extern "C", namespace swift
#endif

Expand Down
12 changes: 12 additions & 0 deletions stdlib/public/SwiftShims/HeapObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

#include "RefCount.h"

#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
// TODO: Should be 8
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 12

#ifdef __cplusplus
#include <type_traits>
#include "swift/Basic/type_traits.h"
Expand Down Expand Up @@ -69,9 +73,17 @@ static_assert(swift::IsTriviallyConstructible<HeapObject>::value,
"HeapObject must be trivially initializable");
static_assert(std::is_trivially_destructible<HeapObject>::value,
"HeapObject must be trivially destructible");

// FIXME: small header for 32-bit
//static_assert(sizeof(HeapObject) == 2*sizeof(void*),
// "HeapObject must be two pointers long");
//
static_assert(sizeof(HeapObject) ==
(sizeof(void*) == 8 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 :
sizeof(void*) == 4 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 :
0 && "unexpected pointer size"),
"HeapObject must match ABI heap object header size");

static_assert(alignof(HeapObject) == alignof(void*),
"HeapObject must be pointer-aligned");

Expand Down
7 changes: 4 additions & 3 deletions stdlib/public/core/KeyPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1414,7 +1414,8 @@ public func _appendingKeyPaths<
}

// The distance in bytes from the address point of a KeyPath object to its
// buffer header. Includes the size of the Swift heap object header and
// buffer header. Includes the size of the Swift heap object header and the
// pointer to the KVC string.

internal var keyPathObjectHeaderSize: Int {
return MemoryLayout<HeapObject>.size + MemoryLayout<Int>.size
Expand All @@ -1437,7 +1438,7 @@ public func swift_getKeyPath(pattern: UnsafeMutableRawPointer,
// global object will itself always have the "trivial" bit set, since it
// never needs to be destroyed.)
// - Components may have unresolved forms that require instantiation.
// - The component type metadata pointers are unresolved, and instead
// - Type metadata pointers are unresolved, and instead
// point to accessor functions that instantiate the metadata.
//
// The pattern never precomputes the capabilities of the key path (readonly/
Expand Down Expand Up @@ -1649,7 +1650,7 @@ internal func _instantiateKeyPathBuffer(
) {
// NB: patternBuffer and destData alias when the pattern is instantiable
// in-line. Therefore, do not read from patternBuffer after the same position
// in destBuffer has been written to.
// in destData has been written to.

var patternBuffer = origPatternBuffer
let destHeaderPtr = origDestData.baseAddress.unsafelyUnwrapped
Expand Down
18 changes: 8 additions & 10 deletions test/IRGen/keypaths.sil
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// TODO: 32-bit support
// REQUIRES: PTRSIZE=64

sil_stage canonical
import Swift
Expand Down Expand Up @@ -64,7 +62,7 @@ sil_vtable C {}
// -- 0x8000_0018 - instantiable in-line, size 4
// CHECK-SAME: i32 -2147483644,
// -- 0x4000_0000 (class) + offset of C.x
// CHECK-32-SAME: i32 1073741832 }>
// CHECK-32-SAME: i32 1073741836 }>
// CHECK-64-SAME: i32 1073741840 }>

// -- %e: C.y
Expand All @@ -75,7 +73,7 @@ sil_vtable C {}
// -- 0x8000_0018 - instantiable in-line, size 4
// CHECK-SAME: i32 -2147483644,
// -- 0x4000_0000 (class) + offset of C.y
// CHECK-32-SAME: i32 1073741836 }>
// CHECK-32-SAME: i32 1073741840 }>
// CHECK-64-SAME: i32 1073741848 }>

// -- %f: C.z
Expand All @@ -86,7 +84,7 @@ sil_vtable C {}
// -- 0x8000_0018 - instantiable in-line, size 4
// CHECK-SAME: i32 -2147483644,
// -- 0x4000_0000 (class) + offset of C.z
// CHECK-32-SAME: i32 1073741848 }>
// CHECK-32-SAME: i32 1073741852 }>
// CHECK-64-SAME: i32 1073741872 }>

// -- %g: S.z.x
Expand All @@ -103,7 +101,7 @@ sil_vtable C {}
// CHECK-64-SAME: i32 32,
// CHECK: %swift.type* (i8*)*
// -- 0x4000_0000 (class) + offset of C.x
// CHECK-32-SAME: i32 1073741832 }>
// CHECK-32-SAME: i32 1073741836 }>
// CHECK-64-SAME: i32 1073741840 }>

// -- %h: C.z.x
Expand All @@ -116,7 +114,7 @@ sil_vtable C {}
// -- 0x8000_0018 - instantiable in-line, size 16
// CHECK-64-SAME: i32 -2147483632,
// -- 0x4000_0000 (class) + offset of C.z
// CHECK-32-SAME: i32 1073741848,
// CHECK-32-SAME: i32 1073741852,
// CHECK-64-SAME: i32 1073741872,
// CHECK: %swift.type* (i8*)*
// -- offset of S.x
Expand All @@ -130,7 +128,7 @@ sil_vtable C {}
// -- 0x8000_0014 - instantiable in-line, size 20
// CHECK-64-SAME: i32 -2147483628,
// -- 0x8000_000c - instantiable in-line, size 12
// CHECK-32-SAME: i32 -2147483640,
// CHECK-32-SAME: i32 -2147483636,
// -- 0x2000_0000 - computed, get-only, identified by function pointer, no args
// CHECK-SAME: i32 536870912,
// CHECK-SAME: void ()* @k_id,
Expand All @@ -144,7 +142,7 @@ sil_vtable C {}
// -- 0x8000_001c - instantiable in-line, size 28
// CHECK-64-SAME: i32 -2147483620,
// -- 0x8000_0010 - instantiable in-line, size 16
// CHECK-32-SAME: i32 -2147483636,
// CHECK-32-SAME: i32 -2147483632,
// -- 0x2a00_0000 - computed, settable, nonmutating, identified by vtable, no args
// CHECK-SAME: i32 704643072,
// CHECK-SAME: [[WORD]]
Expand All @@ -159,7 +157,7 @@ sil_vtable C {}
// -- 0x8000_001c - instantiable in-line, size 28
// CHECK-64-SAME: i32 -2147483620,
// -- 0x8000_0010 - instantiable in-line, size 16
// CHECK-32-SAME: i32 -2147483636,
// CHECK-32-SAME: i32 -2147483632,
// -- 0x3c00_0000 - computed, settable, nonmutating, identified by property offset, no args
// CHECK-SAME: i32 1006632960,
// CHECK-SAME: [[WORD]]
Expand Down
1 change: 0 additions & 1 deletion test/SILGen/keypaths.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// RUN: %target-swift-frontend -enable-experimental-keypaths -emit-silgen %s | %FileCheck %s
// REQUIRES: PTRSIZE=64

struct S<T> {
var x: T
Expand Down
1 change: 0 additions & 1 deletion test/stdlib/KeyPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// RUN: %target-build-swift %s -Xfrontend -enable-experimental-keypaths -o %t/a.out
// RUN: %target-run %t/a.out
// REQUIRES: executable_test
// REQUIRES: PTRSIZE=64

import StdlibUnittest

Expand Down
Loading