Skip to content

Commit 125343d

Browse files
authored
Merge pull request #68735 from kubamracek/embedded-runtime
[embedded] Add a simple Swift runtime, written in embedded Swift
2 parents 6cb608f + a835c6b commit 125343d

19 files changed

+316
-235
lines changed

lib/SILOptimizer/UtilityPasses/Link.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "swift/SILOptimizer/PassManager/Passes.h"
1414
#include "swift/SILOptimizer/PassManager/Transforms.h"
1515
#include "swift/SIL/SILModule.h"
16+
#include "swift/Serialization/SerializedSILLoader.h"
1617

1718
using namespace swift;
1819

@@ -35,8 +36,41 @@ class SILLinker : public SILModuleTransform {
3536
for (auto &Fn : M)
3637
if (M.linkFunction(&Fn, LinkMode))
3738
invalidateAnalysis(&Fn, SILAnalysis::InvalidationKind::Everything);
39+
40+
// In embedded Swift, the stdlib contains all the runtime functions needed
41+
// (swift_retain, etc.). Link them in so they can be referenced in IRGen.
42+
if (M.getASTContext().LangOpts.hasFeature(Feature::Embedded)) {
43+
linkEmbeddedRuntimeFromStdlib();
44+
}
45+
}
46+
47+
void linkEmbeddedRuntimeFromStdlib() {
48+
#define FUNCTION(ID, NAME, CC, AVAILABILITY, RETURNS, ARGS, ATTRS, EFFECT) \
49+
linkEmbeddedRuntimeFunctionByName(#NAME);
50+
51+
#define RETURNS(...)
52+
#define ARGS(...)
53+
#define NO_ARGS
54+
#define ATTRS(...)
55+
#define NO_ATTRS
56+
#define EFFECT(...)
57+
58+
#include "swift/Runtime/RuntimeFunctions.def"
3859
}
3960

61+
void linkEmbeddedRuntimeFunctionByName(StringRef name) {
62+
SILModule &M = *getModule();
63+
64+
// Bail if runtime function is already loaded.
65+
if (M.lookUpFunction(name)) return;
66+
67+
SILFunction *Fn =
68+
M.getSILLoader()->lookupSILFunction(name, SILLinkage::PublicExternal);
69+
if (!Fn) return;
70+
71+
if (M.linkFunction(Fn, LinkMode))
72+
invalidateAnalysis(Fn, SILAnalysis::InvalidationKind::Everything);
73+
}
4074
};
4175
} // end anonymous namespace
4276

stdlib/public/SwiftShims/swift/shims/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(sources
22
AssertionReporting.h
33
CoreFoundationShims.h
4+
EmbeddedShims.h
45
FoundationShims.h
56
GlobalObjects.h
67
HeapObject.h
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===--- EmbeddedShims.h - shims for embedded Swift -------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Shims for embedded Swift.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H
18+
#define SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H
19+
20+
#include "SwiftStddef.h"
21+
#include "Visibility.h"
22+
23+
#if __has_feature(nullability)
24+
#pragma clang assume_nonnull begin
25+
#endif
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
#define SWIFT_CC __attribute__((swiftcall))
32+
#define SWIFT_CONTEXT __attribute__((swift_context))
33+
34+
typedef void SWIFT_CC (*HeapObjectDestroyer)(SWIFT_CONTEXT void *object);
35+
36+
static inline void _swift_runtime_invoke_heap_object_destroy(
37+
const void *destroy, void *self) {
38+
((HeapObjectDestroyer)destroy)(self);
39+
}
40+
41+
#ifdef __cplusplus
42+
} // extern "C"
43+
#endif
44+
45+
#if __has_feature(nullability)
46+
#pragma clang assume_nonnull end
47+
#endif
48+
49+
#endif // SWIFT_STDLIB_SHIMS_EMBEDDEDSHIMS_H

stdlib/public/SwiftShims/swift/shims/LibcShims.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ __swift_size_t _swift_stdlib_fwrite_stdout(const void *ptr, __swift_size_t size,
4040

4141
// General utilities <stdlib.h>
4242
// Memory management functions
43+
extern int posix_memalign(void **memptr, __swift_size_t alignment, __swift_size_t size);
4344
static inline void _swift_stdlib_free(void *_Nullable ptr) {
4445
extern void free(void *_Nullable);
4546
free(ptr);

stdlib/public/SwiftShims/swift/shims/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module SwiftShims {
22
header "AssertionReporting.h"
33
header "CoreFoundationShims.h"
4+
header "EmbeddedShims.h"
45
header "FoundationShims.h"
56
header "GlobalObjects.h"
67
header "HeapObject.h"

stdlib/public/core/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,10 @@ if(SWIFT_STDLIB_ENABLE_VECTOR_TYPES)
254254
list(APPEND SWIFTLIB_GYB_SOURCES SIMDConcreteOperations.swift.gyb SIMDVectorTypes.swift.gyb)
255255
endif()
256256

257-
list(APPEND SWIFTLIB_EMBEDDED_SOURCES EmbeddedStubs.swift)
257+
list(APPEND SWIFTLIB_EMBEDDED_SOURCES
258+
EmbeddedRuntime.swift
259+
EmbeddedStubs.swift
260+
)
258261

259262
set(GROUP_INFO_JSON_FILE ${CMAKE_CURRENT_SOURCE_DIR}/GroupInfo.json)
260263
set(swift_core_link_flags "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}")
@@ -427,6 +430,7 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB)
427430
MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded"
428431
SDK "embedded"
429432
ARCHITECTURE "${arch}"
433+
FILE_DEPENDS ${swiftCore_common_dependencies}
430434
INSTALL_IN_COMPONENT "never_install"
431435
)
432436
add_dependencies(embedded-stdlib embedded-stdlib-${triple})
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftShims
14+
15+
public struct ClassMetadata {
16+
var superclassMetadata: UnsafeMutablePointer<ClassMetadata>?
17+
18+
// There is no way to express the actual calling convention on the heap desroy
19+
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer
20+
// and a helper function in C (_swift_runtime_invoke_heap_object_destroy).
21+
var destroy: UnsafeRawPointer
22+
}
23+
24+
public struct HeapObject {
25+
var metadata: UnsafeMutablePointer<ClassMetadata>
26+
27+
// TODO: This is just an initial support for strong refcounting only. We need
28+
// to think about supporting (or banning) weak and/or unowned references.
29+
var refcount: Int
30+
31+
static let immortalRefCount = -1
32+
}
33+
34+
func alignedAlloc(size: Int, alignment: Int) -> UnsafeMutableRawPointer? {
35+
let alignment = max(alignment, MemoryLayout<UnsafeRawPointer>.size)
36+
var r: UnsafeMutableRawPointer? = nil
37+
_ = posix_memalign(&r, alignment, size)
38+
return r
39+
}
40+
41+
@_cdecl("swift_slowAlloc")
42+
public func swift_slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPointer? {
43+
let alignment: Int
44+
if alignMask == -1 {
45+
alignment = _swift_MinAllocationAlignment
46+
} else {
47+
alignment = alignMask + 1
48+
}
49+
return alignedAlloc(size: size, alignment: alignment)
50+
}
51+
52+
@_cdecl("swift_slowDealloc")
53+
public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer?, _ size: Int, _ alignMask: Int) {
54+
free(ptr)
55+
}
56+
57+
@_silgen_name("swift_allocObject")
58+
public func swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>, requiredSize: Int, requiredAlignmentMask: Int) -> UnsafeMutablePointer<HeapObject> {
59+
let p = swift_slowAlloc(requiredSize, requiredAlignmentMask)!
60+
let object = p.assumingMemoryBound(to: HeapObject.self)
61+
object.pointee.metadata = metadata
62+
object.pointee.refcount = 1
63+
return object
64+
}
65+
66+
@_silgen_name("swift_deallocClassInstance")
67+
public func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, allocatedSize: Int, allocatedAlignMask: Int) {
68+
free(object)
69+
}
70+
71+
@_silgen_name("swift_initStackObject")
72+
public func swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>, object: UnsafeMutablePointer<HeapObject>) -> UnsafeMutablePointer<HeapObject> {
73+
object.pointee.metadata = metadata
74+
75+
// TODO/FIXME: Making all stack promoted objects immortal is not correct.
76+
object.pointee.refcount = HeapObject.immortalRefCount
77+
return object
78+
}
79+
80+
// TODO/FIXME: Refcounting and swift_once is not thread-safe, the following only works in single-threaded environments.
81+
82+
@_silgen_name("swift_isUniquelyReferenced_nonNull_native")
83+
public func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<HeapObject>) -> Bool {
84+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
85+
return object.pointee.refcount == 1
86+
}
87+
88+
@_silgen_name("swift_retain")
89+
public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer {
90+
if Int(Builtin.ptrtoint_Word(object)) == 0 { return object }
91+
let o = UnsafeMutablePointer<HeapObject>(object)
92+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
93+
if o.pointee.refcount == HeapObject.immortalRefCount { return o._rawValue }
94+
o.pointee.refcount += 1
95+
return o._rawValue
96+
}
97+
98+
@_silgen_name("swift_release")
99+
public func swift_release(object: Builtin.RawPointer) {
100+
if Int(Builtin.ptrtoint_Word(object)) == 0 { return }
101+
let o = UnsafeMutablePointer<HeapObject>(object)
102+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
103+
if o.pointee.refcount == HeapObject.immortalRefCount { return }
104+
o.pointee.refcount -= 1
105+
if o.pointee.refcount == 0 {
106+
_swift_runtime_invoke_heap_object_destroy(o.pointee.metadata.pointee.destroy, o)
107+
}
108+
}
109+
110+
@_silgen_name("swift_beginAccess")
111+
public func swift_beginAccess(pointer: UnsafeMutableRawPointer, buffer: UnsafeMutableRawPointer, flags: UInt, pc: UnsafeMutableRawPointer) {
112+
// TODO: Add actual exclusivity checking.
113+
}
114+
115+
@_silgen_name("swift_endAccess")
116+
public func swift_endAccess(buffer: UnsafeMutableRawPointer) {
117+
// TODO: Add actual exclusivity checking.
118+
}
119+
120+
@_silgen_name("swift_once")
121+
public func swift_once(predicate: UnsafeMutablePointer<Int>, fn: (@convention(c) (UnsafeMutableRawPointer)->()), context: UnsafeMutableRawPointer) {
122+
// TODO/FIXME: The following only works in single-threaded environments.
123+
if predicate.pointee == 0 {
124+
predicate.pointee = 1
125+
fn(context)
126+
}
127+
}
128+
129+
@_silgen_name("swift_deletedMethodError")
130+
public func swift_deletedMethodError() -> Never {
131+
Builtin.int_trap()
132+
}

stdlib/public/core/GroupInfo.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@
244244
"Duration.swift",
245245
"DurationProtocol.swift",
246246
"Instant.swift",
247+
"EmbeddedRuntime.swift",
247248
"EmbeddedStubs.swift"
248249
],
249250
"Result": [

test/embedded/Inputs/tiny-runtime-dummy-refcounting.c

Lines changed: 0 additions & 80 deletions
This file was deleted.

0 commit comments

Comments
 (0)