Skip to content

Commit 05255f9

Browse files
dgrove-ossdas
authored andcommitted
Initial Swift3 wrapping overlay for libdispatch
A useful checkpoint along the way to a complete implementation of the Swift3 overlay for libdispatch on non-Objective C platforms. The overlay code builds successfully and simple example programs using queues and timers work as expected. The basic approach is to wrap the C libdispatch objects in Swift objects and make the C dispatch APIs available internally via the CDispatch module. A few pieces (marked with FIXME) are ifdefed out to avoid compilation problems (will get back to them in later commits) or still need to be implemented (release on deinit). Although the installed libdispatch can be used in Swift programs via 'import Dispatch', the swiftc command for the client program currently needs to pass additional command line flags (to be fixed later). For example: swiftc -Xcc -fblocks -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 Forever.swift Signed-off-by: Daniel A. Steffen <dsteffen@apple.com>
1 parent 63b00aa commit 05255f9

16 files changed

+671
-309
lines changed

configure.ac

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ AS_IF([test "x$enable_apple_tsd_optimizations" = "xyes"],
9494
[Define to use non-portable pthread TSD optimizations for Mac OS X)])]
9595
)
9696

97+
AC_CANONICAL_TARGET
98+
9799
#
98100
# Enable building Swift overlay support into libdispatch
99101
#
@@ -102,17 +104,34 @@ AC_ARG_WITH([swift-toolchain],
102104
[swift_toolchain_path=${withval}
103105
AC_DEFINE(HAVE_SWIFT, 1, [Define if building for Swift])
104106
SWIFTC="$swift_toolchain_path/bin/swiftc"
107+
case $target_os in
108+
linux*)
109+
os_string="linux"
110+
;;
111+
*)
112+
os_string=$target_os
113+
;;
114+
esac
115+
SWIFT_LIBDIR="$swift_toolchain_path/lib/swift/$os_string/$target_cpu"
105116
have_swift=true],
106117
[have_swift=false]
107118
)
108119
AM_CONDITIONAL(HAVE_SWIFT, $have_swift)
109120
AC_SUBST([SWIFTC])
121+
AC_SUBST([SWIFT_LIBDIR])
122+
123+
#
124+
# Enable use of gold linker when building the Swift overlay
125+
# to avoid a symbol relocation issue.
126+
# Ultimately the request to use gold should be passed in as an arg
127+
#
128+
AC_CHECK_PROG(use_gold_linker, ld.gold, true, false)
129+
AM_CONDITIONAL(USE_GOLD_LINKER, $use_gold_linker)
110130

111131
#
112132
# Enable __thread based TSD on platforms where it is efficient
113133
# Allow override based on command line argument to configure
114134
#
115-
AC_CANONICAL_TARGET
116135
AC_ARG_ENABLE([thread-local-storage],
117136
[AS_HELP_STRING([--enable-thread-local-storage],
118137
[Enable usage of thread local storage via __thread])],,

dispatch/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ dispatch_HEADERS= \
2424
time.h
2525

2626
if HAVE_SWIFT
27-
dispatch_HEADERS+=module.map
27+
dispatch_HEADERS+=module.modulemap
2828
endif

dispatch/module.map

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

dispatch/module.modulemap

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
module Dispatch [system] [extern_c] {
2-
umbrella header "dispatch.h"
3-
module * { export * }
1+
module Dispatch {
2+
requires blocks
43
export *
4+
link "dispatch"
5+
link "BlocksRuntime"
56
}
67

78
module DispatchIntrospection [system] [extern_c] {
89
header "introspection.h"
910
export *
1011
}
12+
13+
module CDispatch [system] [extern_c] {
14+
umbrella header "dispatch.h"
15+
module * { export * }
16+
export *
17+
requires blocks
18+
link "dispatch"
19+
link "BlocksRuntime"
20+
}

src/Makefile.am

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ libdispatch_la_SOURCES= \
4040
source_internal.h \
4141
trace.h \
4242
voucher_internal.h \
43+
firehose/firehose_internal.h \
4344
shims/atomic.h \
4445
shims/atomic_sfb.h \
4546
shims/getprogname.h \
@@ -83,6 +84,10 @@ libdispatch_la_LDFLAGS+=-Wl,-compatibility_version,1 \
8384
-Wl,-alias_list,$(top_srcdir)/xcodeconfig/libdispatch.aliases
8485
endif
8586

87+
if USE_GOLD_LINKER
88+
libdispatch_la_LDFLAGS+=-Xcompiler -fuse-ld=gold
89+
endif
90+
8691
if USE_OBJC
8792
libdispatch_la_SOURCES+=block.cpp data.m object.m
8893
libdispatch_la_OBJCFLAGS=$(AM_OBJCFLAGS) -Wno-switch -fobjc-gc
@@ -114,43 +119,60 @@ DTRACE_SOURCES=provider.h
114119
endif
115120

116121
if HAVE_SWIFT
117-
libdispatch_la_SOURCES+=swift/Dispatch.mm
118-
EXTRA_libdispatch_la_SOURCES+= \
119-
swift/Dispatch.swift \
122+
SWIFT_SRC_FILES=\
120123
swift/Block.swift \
121124
swift/Data.swift \
122125
swift/Dispatch.swift \
123126
swift/IO.swift \
124127
swift/Private.swift \
125128
swift/Queue.swift \
126129
swift/Source.swift \
127-
swift/Time.swift
128-
129-
EXTRA_libdispatch_la_DEPENDENCIES+=$(abs_builddir)/Dispatch.o $(abs_builddir)/Dispatch.swiftmodule
130-
libdispatch_la_LIBADD+=$(abs_builddir)/Dispatch.o
131-
132-
SWIFT_OBJECTS= \
133-
$(abs_builddir)/Dispatch.swiftmodule \
134-
$(abs_builddir)/Dispatch.swiftdoc \
135-
$(abs_builddir)/Dispatch.o
130+
swift/Time.swift \
131+
swift/Wrapper.swift
132+
133+
SWIFT_ABS_SRC_FILES = $(SWIFT_SRC_FILES:%=$(abs_srcdir)/%)
134+
SWIFT_OBJ_FILES = $(SWIFT_SRC_FILES:%.swift=$(abs_builddir)/%.o)
135+
136+
libdispatch_la_SOURCES+=swift/DispatchStubs.cc
137+
EXTRA_libdispatch_la_SOURCES+=$(SWIFT_SRC_FILES)
138+
139+
EXTRA_libdispatch_la_DEPENDENCIES+=$(SWIFT_OBJ_FILES) $(abs_builddir)/swift/Dispatch.swiftmodule
140+
libdispatch_la_LIBADD+=$(SWIFT_OBJ_FILES)
141+
142+
SWIFT_GEN_FILES= \
143+
$(abs_builddir)/swift/Dispatch.swiftmodule \
144+
$(abs_builddir)/swift/Dispatch.swiftdoc \
145+
$(SWIFT_OBJ_FILES) \
146+
$(SWIFT_OBJ_FILES:%=%.d) \
147+
$(SWIFT_OBJ_FILES:%=%.swiftdeps) \
148+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
149+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdoc) \
150+
$(SWIFT_OBJ_FILES:%=%.~partial.swiftdeps)
151+
152+
SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.modulemap -I$(abs_top_srcdir) -Xcc -fblocks
153+
154+
$(abs_builddir)/swift/%.o: $(abs_srcdir)/swift/%.swift
155+
$(SWIFTC) -frontend -c $(SWIFT_ABS_SRC_FILES) -primary-file $< \
156+
$(SWIFTC_FLAGS) -module-name Dispatch -module-link-name dispatch \
157+
-o $@ -emit-module-path $@.~partial.swiftmodule \
158+
-emit-module-doc-path $@.~partial.swiftdoc -emit-dependencies-path $@.d \
159+
-emit-reference-dependencies-path $@.swiftdeps \
160+
-module-cache-path $(top_builddir)
161+
162+
$(abs_builddir)/swift/Dispatch.swiftmodule: $(SWIFT_ABS_SRC_FILES)
163+
$(SWIFTC) -frontend -emit-module $(SWIFT_OBJ_FILES:%=%.~partial.swiftmodule) \
164+
$(SWIFTC_FLAGS) -module-cache-path $(top_builddir) -module-link-name dispatch \
165+
-o $@ -emit-module-doc-path $(@:%.swiftmodule=%.swiftdoc)
136166

137-
SWIFTC_FLAGS = -Xcc -D__DISPATCH_BUILDING_SWIFT_MODULE__=1 -Xcc -fmodule-map-file=$(abs_top_srcdir)/dispatch/module.map -I$(abs_top_srcdir) -parse-as-library -Xcc -fblocks
138-
139-
$(abs_builddir)/Dispatch.o: $(abs_srcdir)/swift/Dispatch.swift
140-
$(SWIFTC) $(SWIFTC_FLAGS) -c -o $@ $<
141-
142-
$(abs_builddir)/Dispatch.swiftmodule: $(abs_srcdir)/swift/Dispatch.swift
143-
$(SWIFTC) $(SWIFTC_FLAGS) -emit-module -emit-module-path $@ $<
144-
145-
if HAVE_SWIFT
146167
swiftmoddir=${prefix}/lib/swift/linux/${build_cpu}
147-
swiftmod_HEADERS=$(abs_builddir)/Dispatch.swiftmodule $(abs_builddir)/Dispatch.swiftdoc
148-
endif
168+
swiftmod_HEADERS=\
169+
$(abs_builddir)/swift/Dispatch.swiftmodule \
170+
$(abs_builddir)/swift/Dispatch.swiftdoc
149171

150172
endif
151173

152174
BUILT_SOURCES=$(MIG_SOURCES) $(DTRACE_SOURCES)
153175
nodist_libdispatch_la_SOURCES=$(BUILT_SOURCES)
154-
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_OBJECTS)
176+
CLEANFILES=$(BUILT_SOURCES) $(SWIFT_GEN_FILES)
155177
DISTCLEANFILES=pthread_machdep.h pthread System mach objc
156178

src/data.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ const dispatch_block_t _dispatch_data_destructor_none = ^{
108108
DISPATCH_INTERNAL_CRASH(0, "none destructor called");
109109
};
110110

111+
const dispatch_block_t _dispatch_data_destructor_munmap = ^{
112+
DISPATCH_INTERNAL_CRASH(0, "munmap destructor called");
113+
};
114+
111115
#if HAVE_MACH
112116
const dispatch_block_t _dispatch_data_destructor_vm_deallocate = ^{
113117
DISPATCH_INTERNAL_CRASH(0, "vmdeallocate destructor called");

src/swift/Block.swift

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
import CDispatch
14+
1315
public struct DispatchWorkItemFlags : OptionSet, RawRepresentable {
1416
public let rawValue: UInt
1517
public init(rawValue: UInt) { self.rawValue = rawValue }
@@ -38,14 +40,14 @@ public class DispatchWorkItem {
3840
internal var _group: DispatchGroup?
3941

4042
public init(group: DispatchGroup? = nil, qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], block: @convention(block) () -> ()) {
41-
_block = _swift_dispatch_block_create_with_qos_class(__dispatch_block_flags_t(flags.rawValue),
42-
qos.qosClass.rawValue, Int32(qos.relativePriority), block)
43+
_block = dispatch_block_create_with_qos_class(dispatch_block_flags_t(flags.rawValue),
44+
qos.qosClass.rawValue.rawValue, Int32(qos.relativePriority), block)
4345
}
4446

4547
// Used by DispatchQueue.synchronously<T> to provide a @noescape path through
4648
// dispatch_block_t, as we know the lifetime of the block in question.
4749
internal init(flags: DispatchWorkItemFlags = [], noescapeBlock: @noescape () -> ()) {
48-
_block = _swift_dispatch_block_create_noescape(__dispatch_block_flags_t(flags.rawValue), noescapeBlock)
50+
_block = _swift_dispatch_block_create_noescape(dispatch_block_flags_t(flags.rawValue), noescapeBlock)
4951
}
5052

5153
public func perform() {
@@ -57,36 +59,36 @@ public class DispatchWorkItem {
5759
}
5860

5961
public func wait() {
60-
_ = _swift_dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
62+
_ = dispatch_block_wait(_block, DispatchTime.distantFuture.rawValue)
6163
}
6264

6365
public func wait(timeout: DispatchTime) -> DispatchTimeoutResult {
64-
return _swift_dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
66+
return dispatch_block_wait(_block, timeout.rawValue) == 0 ? .Success : .TimedOut
6567
}
6668

6769
public func wait(wallTimeout: DispatchWallTime) -> DispatchTimeoutResult {
68-
return _swift_dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
70+
return dispatch_block_wait(_block, wallTimeout.rawValue) == 0 ? .Success : .TimedOut
6971
}
7072

7173
public func notify(qos: DispatchQoS = .unspecified, flags: DispatchWorkItemFlags = [], queue: DispatchQueue, execute: @convention(block) () -> Void) {
7274
if qos != .unspecified || !flags.isEmpty {
7375
let item = DispatchWorkItem(qos: qos, flags: flags, block: execute)
74-
_swift_dispatch_block_notify(_block, queue, item._block)
76+
dispatch_block_notify(_block, queue.__wrapped, item._block)
7577
} else {
76-
_swift_dispatch_block_notify(_block, queue, execute)
78+
dispatch_block_notify(_block, queue.__wrapped, execute)
7779
}
7880
}
7981

8082
public func notify(queue: DispatchQueue, execute: DispatchWorkItem) {
81-
_swift_dispatch_block_notify(_block, queue, execute._block)
83+
dispatch_block_notify(_block, queue.__wrapped, execute._block)
8284
}
8385

8486
public func cancel() {
85-
_swift_dispatch_block_cancel(_block)
87+
dispatch_block_cancel(_block)
8688
}
8789

8890
public var isCancelled: Bool {
89-
return _swift_dispatch_block_testcancel(_block) != 0
91+
return dispatch_block_testcancel(_block) != 0
9092
}
9193
}
9294

@@ -96,7 +98,7 @@ public extension DispatchWorkItem {
9698
public func wait(timeout: DispatchWallTime) -> Int {
9799
switch wait(wallTimeout: timeout) {
98100
case .Success: return 0
99-
case .TimedOut: return Int(KERN_OPERATION_TIMED_OUT)
101+
case .TimedOut: return DispatchTimeoutResult.KERN_OPERATION_TIMED_OUT
100102
}
101103
}
102104
}
@@ -106,26 +108,7 @@ public extension DispatchWorkItem {
106108
/// C blocks and Swift closures, which interferes with dispatch APIs that depend
107109
/// on the referential identity of a block. Particularly, dispatch_block_create.
108110
internal typealias _DispatchBlock = @convention(block) () -> Void
109-
110-
/// APINotes also removes the old dispatch_block_t typedef from the Dispatch module
111-
/// completely. In doing so it causes the dispatch_block_* API to lose their
112-
/// @convention(block) attributes. As such, all of the entry points are shimmed
113-
//// through Dispatch.mm with _DispatchBlock types.
114-
@_silgen_name("_swift_dispatch_block_create_with_qos_class")
115-
internal func _swift_dispatch_block_create_with_qos_class(_ flags: __dispatch_block_flags_t, _ qos: qos_class_t, _ relativePriority: Int32, _ block: _DispatchBlock) -> _DispatchBlock
111+
internal typealias dispatch_block_t = @convention(block) () -> Void
116112

117113
@_silgen_name("_swift_dispatch_block_create_noescape")
118-
internal func _swift_dispatch_block_create_noescape(_ flags: __dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock
119-
120-
@_silgen_name("_swift_dispatch_block_wait")
121-
internal func _swift_dispatch_block_wait(_ block: _DispatchBlock, _ timeout: UInt64) -> Int
122-
123-
@_silgen_name("_swift_dispatch_block_notify")
124-
internal func _swift_dispatch_block_notify(_ block: _DispatchBlock, _ queue: DispatchQueue, _ notifier: _DispatchBlock)
125-
126-
@_silgen_name("_swift_dispatch_block_cancel")
127-
internal func _swift_dispatch_block_cancel(_ block: _DispatchBlock)
128-
129-
@_silgen_name("_swift_dispatch_block_testcancel")
130-
internal func _swift_dispatch_block_testcancel(_ block: _DispatchBlock) -> Int
131-
114+
internal func _swift_dispatch_block_create_noescape(_ flags: dispatch_block_flags_t, _ block: @noescape () -> ()) -> _DispatchBlock

0 commit comments

Comments
 (0)