Skip to content

Commit 179136f

Browse files
committed
[embedded] Add a simple Swift runtime, written in embedded Swift
1 parent 8fa720d commit 179136f

File tree

13 files changed

+296
-83
lines changed

13 files changed

+296
-83
lines changed

lib/SILOptimizer/UtilityPasses/Link.cpp

Lines changed: 31 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,38 @@ 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+
!M.isStdlibModule()) {
44+
linkEmbeddedRuntimeFromStdlib();
45+
}
46+
}
47+
48+
void linkEmbeddedRuntimeFromStdlib() {
49+
#define FUNCTION(ID, NAME, CC, AVAILABILITY, RETURNS, ARGS, ATTRS, EFFECT) \
50+
linkEmbeddedRuntimeFunctionByName(#NAME);
51+
52+
#define RETURNS(...)
53+
#define ARGS(...)
54+
#define NO_ARGS
55+
#define ATTRS(...)
56+
#define NO_ATTRS
57+
#define EFFECT(...)
58+
59+
#include "swift/Runtime/RuntimeFunctions.def"
3860
}
3961

62+
void linkEmbeddedRuntimeFunctionByName(StringRef name) {
63+
SILModule &M = *getModule();
64+
SILFunction *Fn =
65+
M.getSILLoader()->lookupSILFunction(name, SILLinkage::PublicExternal);
66+
if (!Fn) return;
67+
68+
if (M.linkFunction(Fn, LinkMode))
69+
invalidateAnalysis(Fn, SILAnalysis::InvalidationKind::Everything);
70+
}
4071
};
4172
} // end anonymous namespace
4273

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/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}")
@@ -426,6 +429,7 @@ if(SWIFT_SHOULD_BUILD_EMBEDDED_STDLIB)
426429
MODULE_DIR "${CMAKE_BINARY_DIR}/lib/swift/embedded"
427430
SDK "embedded"
428431
ARCHITECTURE "${arch}"
432+
FILE_DEPENDS ${swiftCore_common_dependencies}
429433
INSTALL_IN_COMPONENT "never_install"
430434
)
431435
add_dependencies(embedded-stdlib embedded-stdlib-${triple})
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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+
var refcount: Int
27+
}
28+
29+
@_silgen_name("posix_memalign")
30+
func posix_memalign(_: UnsafeMutablePointer<UnsafeMutableRawPointer?>, _: UInt, _: UInt) -> CInt
31+
32+
func alignedAlloc(size: UInt, alignment: UInt) -> UnsafeMutableRawPointer? {
33+
let alignment = max(alignment, UInt(MemoryLayout<UnsafeRawPointer>.size))
34+
var r: UnsafeMutableRawPointer? = nil
35+
_ = posix_memalign(&r, alignment, size)
36+
return r
37+
}
38+
39+
@_cdecl("swift_slowAlloc")
40+
public func swift_slowAlloc(_ size: UInt, _ alignMask: UInt) -> UnsafeMutableRawPointer? {
41+
let alignment: UInt
42+
if alignMask == UInt.max {
43+
alignment = UInt(_swift_MinAllocationAlignment)
44+
} else {
45+
alignment = alignMask + 1
46+
}
47+
return alignedAlloc(size: size, alignment: alignment)
48+
}
49+
50+
@_cdecl("swift_slowDealloc")
51+
public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer?, _ size: UInt, _ alignMask: UInt) {
52+
free(ptr)
53+
}
54+
55+
@_silgen_name("swift_allocObject")
56+
public func swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>, requiredSize: UInt, requiredAlignmentMask: UInt) -> UnsafeMutablePointer<HeapObject> {
57+
let p = swift_slowAlloc(requiredSize, requiredAlignmentMask)!
58+
let object = p.assumingMemoryBound(to: HeapObject.self)
59+
object.pointee.metadata = metadata
60+
object.pointee.refcount = 1
61+
return object
62+
}
63+
64+
@_silgen_name("swift_deallocClassInstance")
65+
public func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, allocatedSize: UInt, allocatedAlignMask: UInt) {
66+
free(object)
67+
}
68+
69+
@_silgen_name("swift_initStackObject")
70+
public func swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>, object: UnsafeMutablePointer<HeapObject>) -> UnsafeMutablePointer<HeapObject> {
71+
object.pointee.metadata = metadata
72+
object.pointee.refcount = -1
73+
return object
74+
}
75+
76+
// TODO/FIXME: Refcounting and swift_once is not thread-safe, the following only works in single-threaded environments.
77+
78+
@_silgen_name("swift_isUniquelyReferenced_nonNull_native")
79+
public func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<HeapObject>) -> Bool {
80+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
81+
return object.pointee.refcount == 1
82+
}
83+
84+
@_silgen_name("swift_retain")
85+
public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer {
86+
if Int(Builtin.ptrtoint_Word(object)) == 0 { return object }
87+
let o = UnsafeMutablePointer<HeapObject>(object)
88+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
89+
if o.pointee.refcount == -1 { return o._rawValue }
90+
o.pointee.refcount += 1
91+
return o._rawValue
92+
}
93+
94+
@_silgen_name("swift_release")
95+
public func swift_release(object: Builtin.RawPointer) {
96+
if Int(Builtin.ptrtoint_Word(object)) == 0 { return }
97+
let o = UnsafeMutablePointer<HeapObject>(object)
98+
// TODO/FIXME: Refcounting is not thread-safe, the following only works in single-threaded environments.
99+
if o.pointee.refcount == -1 { return }
100+
o.pointee.refcount -= 1
101+
if o.pointee.refcount == 0 {
102+
_swift_runtime_invoke_heap_object_destroy(o.pointee.metadata.pointee.destroy, o)
103+
}
104+
}
105+
106+
@_silgen_name("swift_beginAccess")
107+
public func swift_beginAccess(pointer: UnsafeMutableRawPointer, buffer: UnsafeMutableRawPointer, flags: UInt, pc: UnsafeMutableRawPointer) {
108+
}
109+
110+
@_silgen_name("swift_endAccess")
111+
public func swift_endAccess(buffer: UnsafeMutableRawPointer) {
112+
}
113+
114+
@_silgen_name("swift_once")
115+
public func swift_once(predicate: UnsafeMutablePointer<Int>, fn: (@convention(c) (UnsafeMutableRawPointer)->()), context: UnsafeMutableRawPointer) {
116+
// TODO/FIXME: The following only works in single-threaded environments.
117+
if predicate.pointee == 0 {
118+
predicate.pointee = 1
119+
fn(context)
120+
}
121+
}

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 & 74 deletions
This file was deleted.

test/embedded/array-to-pointer.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -c -o %t/main.o
3-
// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o
43
// RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o
5-
// RUN: %target-clang %t/main.o %t/runtime.o %t/print.o -o %t/a.out -dead_strip
4+
// RUN: %target-clang %t/main.o %t/print.o -o %t/a.out -dead_strip
65
// RUN: %target-run %t/a.out | %FileCheck %s
76

87
// REQUIRES: executable_test

test/embedded/arrays.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -c -o %t/main.o
3-
// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o
43
// RUN: %target-clang -x c -c %S/Inputs/print.c -o %t/print.o
5-
// RUN: %target-clang %t/main.o %t/runtime.o %t/print.o -o %t/a.out -dead_strip
4+
// RUN: %target-clang %t/main.o %t/print.o -o %t/a.out -dead_strip
65
// RUN: %target-run %t/a.out | %FileCheck %s
76

87
// REQUIRES: executable_test

test/embedded/classes-arrays.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -c -o %t/main.o
3-
// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o
4-
// RUN: %target-clang %t/main.o %t/runtime.o -o %t/a.out -dead_strip
3+
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
54
// RUN: %target-run %t/a.out | %FileCheck %s
65

76
// REQUIRES: executable_test

test/embedded/classes.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -c -o %t/main.o
3-
// RUN: %target-clang -x c -c %S/Inputs/tiny-runtime-dummy-refcounting.c -o %t/runtime.o
4-
// RUN: %target-clang %t/main.o %t/runtime.o -o %t/a.out -dead_strip
3+
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
54
// RUN: %target-run %t/a.out | %FileCheck %s
65

76
// REQUIRES: executable_test

0 commit comments

Comments
 (0)