Skip to content
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

[WebAssembly] Add ifdefs for the WASI target #29530

Merged
merged 1 commit into from Feb 13, 2020

Conversation

MaxDesiatov
Copy link
Member

Disables/enables stdlib and IRGen code appropriately when targeting WebAssembly/WASI.

This is a part of SR-9307 and #24684.

(cc @kateinoigakukun)

Copy link
Collaborator

@compnerd compnerd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a huge change. Please split this up into more focused changes. There can be a single change for the runtime, and a single change for the standard library at least.

include/swift/SwiftRemoteMirror/Platform.h Outdated Show resolved Hide resolved
include/swift/SwiftRemoteMirror/Platform.h Outdated Show resolved Hide resolved
@@ -165,6 +165,12 @@ swift::getIRTargetOptions(const IRGenOptions &Opts, ASTContext &Ctx) {
TargetOpts.FunctionSections = Opts.FunctionSections;

auto *Clang = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());

// WebAssembly doesn't support atomics yet, see https://bugs.swift.org/browse/SR-12097
if (Clang->getTargetInfo().getTriple().isOSBinFormatWasm()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extraneous braces. IIRC, we set the ThreadModel for cygwin/MinGW as well. Can we please set the thread model at one site?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I'm aware this is a single place where ThreadModel is used in the whole Swift project, it's not set for Cygwin anywhere. The only somewhat related settings for Cygwin that I see are set in createTargetMachine, but that doesn't give access to TargetOpts:

  if (EffectiveTriple.isArch64Bit() && EffectiveTriple.isWindowsCygwinEnvironment())
    cmodel = CodeModel::Large;

stdlib/private/StdlibUnittest/InterceptTraps.cpp Outdated Show resolved Hide resolved
stdlib/private/StdlibUnittest/RaceTest.swift Show resolved Hide resolved
import Glibc
#elseif os(Windows)
import MSVCRT
import WinSDK
#endif

internal func _signalToString(_ signal: Int) -> String {
#if os(WASI)
// no signals support on WASI yet, see https://github.com/WebAssembly/WASI/issues/166
fatalError("\(#function) is not supported on WebAssembly/WASI")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that you should stub out _signalToString. Instead, you need to die earlier at the point where the signal is being handled. Just drop the entire function on WASI.

// WASI doesn't support child processes
public func spawnChild(_ args: [String])
-> (pid: pid_t, stdinFD: CInt, stdoutFD: CInt, stderrFD: CInt) {
preconditionFailure("\(#function) is not supported on WebAssembly/WASI")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fatalError, not preconditionFailure.

preconditionFailure("\(#function) is not supported on WebAssembly/WASI")
}
public func posixWaitpid(_ pid: pid_t) -> ProcessTerminationStatus {
preconditionFailure("\(#function) is not supported on WebAssembly/WASI")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar

@@ -125,6 +125,8 @@ public func _stdlib_pipe() -> (readEnd: CInt, writeEnd: CInt, error: CInt) {
let ret = fds.withUnsafeMutableBufferPointer { unsafeFds -> CInt in
#if os(Windows)
return _pipe(unsafeFds.baseAddress, 0, 0)
#elseif os(WASI)
preconditionFailure("no pipes available on WebAssembly/WASI")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, this is largely used for the reflection tests. Perhaps we should just disable the reflection tests instead. I really think that given the amount of stuff not available in WASI libc yet, the focus should be improving that first (which is why I stopped and started looking at WASI libc instead).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is used in RaceTest.swift in the implementation of _InterruptibleSleep on non-Windows platforms. Would _InterruptibleSleep need a dedicated implementation for WASI instead? Could WebAssembly/WASI#77 be somewhat related?

@@ -12,7 +12,7 @@

#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku) || os(WASI)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it might be better to just not build SwiftPrivateThreadExtras on WASI

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would make RaceTest that uses SwiftPrivateThreadExtras disabled, requiring us to disable quite a few tests. Do you think that be worth it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to disabling the whole module, if it leads to simpler code. Race tests would not work (and are pointless) without threads anyway.

#endif
#endif // _WIN32

#endif // __wasi__
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the endif should be before the definition of VectoredCrashHandler.

@@ -562,7 +562,12 @@ class _InterruptibleSleep {
return
}

#if os(WASI)
// WebAssembly/WASI on wasm32 is the only 32-bit platform with Int64 time_t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everywhere throughout this patch, I'd appreciate periods at the end of comments.

@@ -562,7 +562,12 @@ class _InterruptibleSleep {
return
}

#if os(WASI)
// WebAssembly/WASI on wasm32 is the only 32-bit platform with Int64 time_t
var timeout = timeval(tv_sec: time_t(duration), tv_usec: 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the code would still compile on other platforms if you the time_t(duration) variant everywhere (no conditional compilation).

@@ -98,6 +98,9 @@ public func _stdlib_thread_create_block<Argument, Result>(
} else {
return (0, ThreadHandle(bitPattern: threadID))
}
#elseif os(WASI)
// WASI environment has only a single thread, see https://bugs.swift.org/browse/SR-12097
return (0, nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pthread_create returns 0 on success. Please return an appropriate errno, like ENOTSUP.

@@ -128,6 +131,9 @@ public func _stdlib_thread_join<Result>(
} else {
return (CInt(result), nil)
}
#elseif os(WASI)
// WASI environment has only a single thread, see https://bugs.swift.org/browse/SR-12097
return (0, nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, please return EINVAL.

@@ -35,7 +35,9 @@ public struct _stdlib_thread_barrier_t {
var cond: UnsafeMutablePointer<CONDITION_VARIABLE>?
#elseif os(Cygwin) || os(FreeBSD)
var mutex: UnsafeMutablePointer<pthread_mutex_t?>?
var cond: UnsafeMutablePointer<pthread_cond_t?>?
var cond: UnsafeMutablePointer<pthread_cond_t?>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we lost a question mark on this line.

var cond: UnsafeMutablePointer<pthread_cond_t?>?
var cond: UnsafeMutablePointer<pthread_cond_t?>
#elseif os(WASI)
// WASI environment has a only single thread, see https://bugs.swift.org/browse/SR-12097
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the code will pretend to succeed, which does not sound great. Can we produce an error?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this comment refer to some function? It's currently positioned within a struct property declaration, do you mean that the structs init should invoke fatalError or preconditionFailure when it runs on WASI?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about sloppy commenting -- yes, I was trying to attach the comment to the init, and invoking fatalError is exactly what I meant.

@@ -379,7 +379,7 @@ internal var _objectPointerLowSpareBitShift: UInt {
}

#if arch(i386) || arch(arm) || arch(powerpc64) || arch(powerpc64le) || arch(
s390x)
s390x) || arch(wasm32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe group wasm32 together with the other 32-bit platforms? (That is, i386, arm, wasm32, and then everything else.)

@MaxDesiatov MaxDesiatov force-pushed the swiftwasm-ifdefs branch 2 times, most recently from e3c7637 to 50e5c4a Compare January 29, 2020 22:28
@kateinoigakukun
Copy link
Member

kateinoigakukun commented Jan 30, 2020

@MaxDesiatov Could you reflect this change also for WASI? #29536
This prevents from building WASI target stdlib

build log

stdlib/private/StdlibUnittest/SymbolLookup.swift Outdated Show resolved Hide resolved
stdlib/private/SwiftPrivateLibcExtras/Subprocess.c Outdated Show resolved Hide resolved
stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift Outdated Show resolved Hide resolved
@@ -12,7 +12,7 @@

#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku) || os(WASI)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 to disabling the whole module, if it leads to simpler code. Race tests would not work (and are pointless) without threads anyway.

@@ -380,7 +382,7 @@ public var SEM_FAILED: UnsafeMutablePointer<sem_t>? {
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
// The value is ABI. Value verified to be correct for OS X, iOS, watchOS, tvOS.
return UnsafeMutablePointer<sem_t>(bitPattern: -1)
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku) || os(WASI)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does sem_open() exist and work on WASI? If not, ifdef out the whole variable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does exist and whole semaphore.h is available too.

@@ -65,7 +65,7 @@ internal func _swift_stdlib_atomicCompareExchangeStrongInt(
object target: UnsafeMutablePointer<Int>,
expected: UnsafeMutablePointer<Int>,
desired: Int) -> Bool {
#if arch(i386) || arch(arm)
#if arch(i386) || arch(arm) || arch(wasm32)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other comments that you left say that WebAssembly has no atomics right now. So how do these functions get compiled? Regular loads and stores?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is set in IRGen.cpp change in this same PR:

  if (Clang->getTargetInfo().getTriple().isOSBinFormatWasm())
    TargetOpts.ThreadModel = llvm::ThreadModel::Single;

@MaxDesiatov
Copy link
Member Author

Hi @gribozavr @compnerd I've addressed your feedback and added comments with clarifications, could you have another look. Thank you!

@gribozavr
Copy link
Collaborator

I don't see where in the patch you disable building SwiftPrivateThreadExtras on WASI...

If you want to submit this change as an incremental improvement, LGTM, but just noting that it seems that some work is still needed to disable building some modules.

@MaxDesiatov
Copy link
Member Author

@gribozavr in stdlib/private/StdlibUnittest/CMakeLists.txt there's no SWIFT_MODULE_DEPENDS_WASI yet, but when it's there it won't specify SwiftPrivateThreadExtras to exclude that dependency. SWIFT_MODULE_DEPENDS_WASI implementation would come in a future PR that updates the build system and CMake code.

Would you mind triggering CI for this PR? Thanks again for your help.

@gribozavr
Copy link
Collaborator

@MaxDesiatov That will avoid linking the StdlibUnittest against SwiftPrivateThreadExtras, but still won't exclude SwiftPrivateThreadExtras from being built, I believe. PTAL at TARGET_SDKS as used in stdlib/public/Platform/CMakeLists.txt, for example.

@gribozavr
Copy link
Collaborator

@swift-ci Please test

@swift-ci
Copy link
Collaborator

swift-ci commented Feb 7, 2020

Build failed
Swift Test Linux Platform
Git Sha - 1d7e592ae5fe216a342c1ba3b874d126cd61ee1f

@swift-ci
Copy link
Collaborator

swift-ci commented Feb 7, 2020

Build failed
Swift Test OS X Platform
Git Sha - 1d7e592ae5fe216a342c1ba3b874d126cd61ee1f

@MaxDesiatov
Copy link
Member Author

MaxDesiatov commented Feb 9, 2020

@gribozavr I've updated CMakeLists.txt to use the TARGET_SDKS argument instead of SWIFT_MODULE_DEPENDS, also rebased the PR on top of master, as the CI issue seems to be caused by the branch being too out of sync:

swiftpm/Sources/PackageLoading/Diagnostics.swift:11:8: error: 
compiled module was created by a newer version of the compiler: 
buildbot_incremental/swiftpm-macosx-x86_64/x86_64-apple-macosx/tsc/swift/TSCBasic.swiftmodule

Could you trigger another CI run? Thanks

@gribozavr
Copy link
Collaborator

I think we need both TARGET_SDKS (to prevent the module from being built when you build everything that's available), and SWIFT_MODULE_DEPENDS (to prevent other modules from depending on it when it is not available.)

@MaxDesiatov
Copy link
Member Author

@gribozavr yeah, it does have both, I've restored SWIFT_MODULE_DEPENDS to its original state. As far as I understand, when SWIFT_MODULE_DEPENDS_WASI is available we'd just add that with a corresponding setting, while TARGET_SDKS should be enough for now to avoid building it for WASI.

@gribozavr
Copy link
Collaborator

@swift-ci Please test

@gribozavr
Copy link
Collaborator

@swift-ci Please smoke test

@MaxDesiatov
Copy link
Member Author

Thanks for triggering CI! As it has passed and PR got the approval, can it be merged now to avoid potential conflicts appearing and preventing it from being merged as the diff is big enough?

@stephentyrone
Copy link
Member

In StringObject.swift, you seem to be missing arch(wasm32) in the very first conditional, defining the string layout. If that's the case, am I correct in believing that none of this is actually tested for wasm?

@MaxDesiatov
Copy link
Member Author

Do you mean line 80 that precedes internal enum Variant? That one has a corresponding #else which does the job for other platforms in my understanding, but I can't confirm that it works for WASI at the moment. Will need to have a closer look if some of our failing tests have any relation to it, we are slowly enabling the test suite here in swiftwasm#12 and swiftwasm#30. If it does fail, I'd be happy to fix it in a follow-up PR.

@stephentyrone
Copy link
Member

Yes, that one; the fields of a _StringObject are radically different on 32-bit platforms than they are on 64-bit platforms; if you have the wrong definition (as I think you do), it shouldn't even build.

@MaxDesiatov
Copy link
Member Author

Well, it does build it seems, but thanks for having a look, I'll keep that in mind 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants