-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[embedded] Add a simple Swift runtime, written in embedded Swift #68735
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
Changes from all commits
86ad378
0758e7d
72e311d
497b810
cf1d19e
45c2dd7
a835c6b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
//===--- EmbeddedShims.h - shims for embedded Swift -------------*- C++ -*-===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2018 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Shims for embedded Swift. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H | ||
#define SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H | ||
|
||
#include "SwiftStddef.h" | ||
#include "Visibility.h" | ||
|
||
#if __has_feature(nullability) | ||
#pragma clang assume_nonnull begin | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#define SWIFT_CC __attribute__((swiftcall)) | ||
#define SWIFT_CONTEXT __attribute__((swift_context)) | ||
|
||
typedef void SWIFT_CC (*HeapObjectDestroyer)(SWIFT_CONTEXT void *object); | ||
|
||
static inline void _swift_runtime_invoke_heap_object_destroy( | ||
const void *destroy, void *self) { | ||
((HeapObjectDestroyer)destroy)(self); | ||
} | ||
|
||
#ifdef __cplusplus | ||
} // extern "C" | ||
#endif | ||
|
||
#if __has_feature(nullability) | ||
#pragma clang assume_nonnull end | ||
#endif | ||
|
||
#endif // SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import SwiftShims | ||
al45tair marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
public struct ClassMetadata { | ||
var superclassMetadata: UnsafeMutablePointer<ClassMetadata>? | ||
|
||
// There is no way to express the actual calling convention on the heap desroy | ||
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer | ||
// and a helper function in C (_swift_runtime_invoke_heap_object_destroy). | ||
var destroy: UnsafeRawPointer | ||
} | ||
|
||
public struct HeapObject { | ||
var metadata: UnsafeMutablePointer<ClassMetadata> | ||
|
||
// TODO: This is just an initial support for strong refcounting only. We need | ||
// to think about supporting (or banning) weak and/or unowned references. | ||
var refcount: Int | ||
kubamracek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
static let immortalRefCount = -1 | ||
} | ||
|
||
func alignedAlloc(size: Int, alignment: Int) -> UnsafeMutableRawPointer? { | ||
let alignment = max(alignment, MemoryLayout<UnsafeRawPointer>.size) | ||
var r: UnsafeMutableRawPointer? = nil | ||
_ = posix_memalign(&r, alignment, size) | ||
return r | ||
} | ||
|
||
@_cdecl("swift_slowAlloc") | ||
public func swift_slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPointer? { | ||
let alignment: Int | ||
if alignMask == -1 { | ||
alignment = _swift_MinAllocationAlignment | ||
} else { | ||
alignment = alignMask + 1 | ||
} | ||
return alignedAlloc(size: size, alignment: alignment) | ||
} | ||
|
||
@_cdecl("swift_slowDealloc") | ||
public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer?, _ size: Int, _ alignMask: Int) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you going to add the DO_NOT_FREE_BIT here, too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it should go here...? I thought swift_slowDealloc is not used on refcounted objects, and only used to implement things like UnsafePointer.deallocate(). This matches how swift_slowDealloc is implemented in the main runtime (no checking of anything, just a direct call to free). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah sorry, I meant to add this comment for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aha, then yes -- let me do that as a follow-up in https://github.com/apple/swift/pull/68754/files, I'll rebase it on top of this Swift runtime. |
||
free(ptr) | ||
} | ||
|
||
@_silgen_name("swift_allocObject") | ||
public func swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>, requiredSize: Int, requiredAlignmentMask: Int) -> UnsafeMutablePointer<HeapObject> { | ||
let p = swift_slowAlloc(requiredSize, requiredAlignmentMask)! | ||
let object = p.assumingMemoryBound(to: HeapObject.self) | ||
object.pointee.metadata = metadata | ||
object.pointee.refcount = 1 | ||
return object | ||
} | ||
|
||
@_silgen_name("swift_deallocClassInstance") | ||
public func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, allocatedSize: Int, allocatedAlignMask: Int) { | ||
free(object) | ||
} | ||
|
||
@_silgen_name("swift_initStackObject") | ||
public func swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>, object: UnsafeMutablePointer<HeapObject>) -> UnsafeMutablePointer<HeapObject> { | ||
object.pointee.metadata = metadata | ||
|
||
// TODO/FIXME: Making all stack promoted objects immortal is not correct. | ||
object.pointee.refcount = HeapObject.immortalRefCount | ||
return object | ||
} | ||
|
||
// TODO/FIXME: Refcounting and swift_once is not thread-safe, the following only works in single-threaded environments. | ||
|
||
@_silgen_name("swift_isUniquelyReferenced_nonNull_native") | ||
public func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<HeapObject>) -> Bool { | ||
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. | ||
return object.pointee.refcount == 1 | ||
} | ||
|
||
@_silgen_name("swift_retain") | ||
public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer { | ||
if Int(Builtin.ptrtoint_Word(object)) == 0 { return object } | ||
let o = UnsafeMutablePointer<HeapObject>(object) | ||
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. | ||
if o.pointee.refcount == HeapObject.immortalRefCount { return o._rawValue } | ||
o.pointee.refcount += 1 | ||
return o._rawValue | ||
} | ||
|
||
@_silgen_name("swift_release") | ||
public func swift_release(object: Builtin.RawPointer) { | ||
if Int(Builtin.ptrtoint_Word(object)) == 0 { return } | ||
let o = UnsafeMutablePointer<HeapObject>(object) | ||
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments. | ||
if o.pointee.refcount == HeapObject.immortalRefCount { return } | ||
o.pointee.refcount -= 1 | ||
if o.pointee.refcount == 0 { | ||
_swift_runtime_invoke_heap_object_destroy(o.pointee.metadata.pointee.destroy, o) | ||
} | ||
} | ||
|
||
@_silgen_name("swift_beginAccess") | ||
public func swift_beginAccess(pointer: UnsafeMutableRawPointer, buffer: UnsafeMutableRawPointer, flags: UInt, pc: UnsafeMutableRawPointer) { | ||
kubamracek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// TODO: Add actual exclusivity checking. | ||
} | ||
|
||
@_silgen_name("swift_endAccess") | ||
public func swift_endAccess(buffer: UnsafeMutableRawPointer) { | ||
// TODO: Add actual exclusivity checking. | ||
} | ||
|
||
@_silgen_name("swift_once") | ||
public func swift_once(predicate: UnsafeMutablePointer<Int>, fn: (@convention(c) (UnsafeMutableRawPointer)->()), context: UnsafeMutableRawPointer) { | ||
// TODO/FIXME: The following only works in single-threaded environments. | ||
if predicate.pointee == 0 { | ||
predicate.pointee = 1 | ||
fn(context) | ||
} | ||
} | ||
|
||
@_silgen_name("swift_deletedMethodError") | ||
public func swift_deletedMethodError() -> Never { | ||
Builtin.int_trap() | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super cool that you can just put this into the stdlib!