diff --git a/include/swift/AST/DiagnosticsClangImporter.def b/include/swift/AST/DiagnosticsClangImporter.def index e69e86127028a..7c6fa4e96c744 100644 --- a/include/swift/AST/DiagnosticsClangImporter.def +++ b/include/swift/AST/DiagnosticsClangImporter.def @@ -118,8 +118,8 @@ WARNING(nonmutating_without_mutable_fields,none, ERROR(module_map_not_found, none, "module map file '%0' not found", (StringRef)) -WARNING(glibc_not_found, none, - "glibc not found for '%0'; C stdlib may be unavailable", +WARNING(libc_not_found, none, + "libc not found for '%0'; C stdlib may be unavailable", (StringRef)) WARNING(libstdcxx_not_found, none, "libstdc++ not found for '%0'; C++ stdlib may be unavailable", diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 313af3145b2ae..b7dbee1dd9c7f 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -89,18 +89,6 @@ static llvm::Optional getInjectedModuleMapPath( return path; } -/// Finds the glibc.modulemap file relative to the provided resource dir. -/// -/// Note that the module map used for Glibc depends on the target we're -/// compiling for, and is not included in the resource directory with the other -/// implicit module maps. It's at {freebsd|linux}/{arch}/glibc.modulemap. -static llvm::Optional getGlibcModuleMapPath( - SearchPathOptions &Opts, const llvm::Triple &triple, - const llvm::IntrusiveRefCntPtr &vfs) { - return getActualModuleMapPath("glibc.modulemap", Opts, triple, - /*isArchSpecific*/ true, vfs); -} - static llvm::Optional getLibStdCxxModuleMapPath( SearchPathOptions &opts, const llvm::Triple &triple, const llvm::IntrusiveRefCntPtr &vfs) { @@ -190,19 +178,20 @@ createClangArgs(const ASTContext &ctx, clang::driver::Driver &clangDriver) { return clangDriverArgs; } -static bool shouldInjectGlibcModulemap(const llvm::Triple &triple) { +static bool shouldInjectLibcModulemap(const llvm::Triple &triple) { return triple.isOSGlibc() || triple.isOSOpenBSD() || triple.isOSFreeBSD() || - triple.isAndroid(); + triple.isAndroid() || triple.isOSWASI(); } -static SmallVector, 2> getGlibcFileMapping( - ASTContext &ctx, - const llvm::IntrusiveRefCntPtr &vfs) { +static SmallVector, 2> +getLibcFileMapping(ASTContext &ctx, StringRef modulemapFileName, + std::optional maybeHeaderFileName, + const llvm::IntrusiveRefCntPtr &vfs) { const llvm::Triple &triple = ctx.LangOpts.Target; - if (!shouldInjectGlibcModulemap(triple)) + if (!shouldInjectLibcModulemap(triple)) return {}; - // Extract the Glibc path from Clang driver. + // Extract the libc path from Clang driver. auto clangDriver = createClangDriver(ctx, vfs); auto clangDriverArgs = createClangArgs(ctx, clangDriver); @@ -212,42 +201,47 @@ static SmallVector, 2> getGlibcFileMapping( clangToolchain.AddClangSystemIncludeArgs(clangDriverArgs, includeArgStrings); auto parsedIncludeArgs = parseClangDriverArgs(clangDriver, includeArgStrings); - // Find the include path that contains Glibc headers. We use three arbitrarily - // chosen headers to determine if the include path actually contains Glibc. + // Find the include path that contains libc headers. We use three arbitrarily + // chosen headers to determine if the include path actually contains libc. // Ideally we would check that all of the headers referenced from the // modulemap are present. - Path glibcDir; + Path libcDir; if (auto dir = findFirstIncludeDir( parsedIncludeArgs, {"inttypes.h", "unistd.h", "stdint.h"}, vfs)) { - glibcDir = dir.value(); + libcDir = dir.value(); } else { - ctx.Diags.diagnose(SourceLoc(), diag::glibc_not_found, triple.str()); + ctx.Diags.diagnose(SourceLoc(), diag::libc_not_found, triple.str()); return {}; } Path actualModuleMapPath; - if (auto path = getGlibcModuleMapPath(ctx.SearchPathOpts, triple, vfs)) + if (auto path = getActualModuleMapPath(modulemapFileName, ctx.SearchPathOpts, + triple, /*isArchSpecific*/ true, vfs)) actualModuleMapPath = path.value(); else // FIXME: Emit a warning of some kind. return {}; - // TODO: remove the SwiftGlibc.h header and reference all Glibc headers - // directly from the modulemap. - Path actualHeaderPath = actualModuleMapPath; - llvm::sys::path::remove_filename(actualHeaderPath); - llvm::sys::path::append(actualHeaderPath, "SwiftGlibc.h"); - - Path injectedModuleMapPath(glibcDir); + Path injectedModuleMapPath(libcDir); llvm::sys::path::append(injectedModuleMapPath, "module.modulemap"); + SmallVector, 2> vfsMappings{ + {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)}}; - Path injectedHeaderPath(glibcDir); - llvm::sys::path::append(injectedHeaderPath, "SwiftGlibc.h"); + if (maybeHeaderFileName) { + // TODO: remove the SwiftGlibc.h header and reference all Glibc headers + // directly from the modulemap. + Path actualHeaderPath = actualModuleMapPath; + llvm::sys::path::remove_filename(actualHeaderPath); + llvm::sys::path::append(actualHeaderPath, maybeHeaderFileName.value()); - return { - {std::string(injectedModuleMapPath), std::string(actualModuleMapPath)}, - {std::string(injectedHeaderPath), std::string(actualHeaderPath)}, - }; + Path injectedHeaderPath(libcDir); + llvm::sys::path::append(injectedHeaderPath, maybeHeaderFileName.value()); + + vfsMappings.push_back( + {std::string(injectedHeaderPath), std::string(actualHeaderPath)}); + } + + return vfsMappings; } static void getLibStdCxxFileMapping( @@ -518,8 +512,19 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( ClangInvocationFileMapping result; if (!vfs) vfs = llvm::vfs::getRealFileSystem(); - // Android/BSD/Linux Mappings - result.redirectedFiles.append(getGlibcFileMapping(ctx, vfs)); + + const llvm::Triple &triple = ctx.LangOpts.Target; + + if (triple.isOSWASI()) { + // WASI Mappings + result.redirectedFiles.append( + getLibcFileMapping(ctx, "wasi-libc.modulemap", std::nullopt, vfs)); + } else { + // Android/BSD/Linux Mappings + result.redirectedFiles.append(getLibcFileMapping( + ctx, "glibc.modulemap", StringRef("SwiftGlibc.h"), vfs)); + } + if (ctx.LangOpts.EnableCXXInterop) getLibStdCxxFileMapping(result, ctx, vfs); diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt index 18be6412cf33e..1e18c911064a6 100644 --- a/stdlib/public/Platform/CMakeLists.txt +++ b/stdlib/public/Platform/CMakeLists.txt @@ -114,6 +114,23 @@ add_swift_target_library(swiftMusl ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OV TARGET_SDKS MUSL INSTALL_IN_COMPONENT sdk-overlay) +add_swift_target_library(swiftWASILibc ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY + ${swift_platform_sources} + POSIXError.swift + + GYB_SOURCES + ${swift_platform_gyb_sources} + WASILibc.swift.gyb + + SWIFT_COMPILE_FLAGS + ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} + ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} + ${swift_platform_compile_flags} + LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}" + TARGET_SDKS WASI + INSTALL_IN_COMPONENT sdk-overlay + DEPENDS wasilibc_modulemap) + add_swift_target_library(swiftCRT ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY ucrt.swift ${swift_platform_sources} @@ -234,6 +251,43 @@ add_custom_target(glibc_modulemap DEPENDS ${glibc_modulemap_target_list}) set_property(TARGET glibc_modulemap PROPERTY FOLDER "Miscellaneous") add_dependencies(sdk-overlay glibc_modulemap) +set(wasilibc_modulemap_target_list) +if("WASI" IN_LIST SWIFT_SDKS) + set(wasilibc_modulemap_source "wasi-libc.modulemap") + foreach(arch ${SWIFT_SDK_WASI_ARCHITECTURES}) + set(arch_subdir "${SWIFT_SDK_WASI_LIB_SUBDIR}/${arch}") + set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}") + set(module_dir_static "${SWIFTSTATICLIB_DIR}/${arch_subdir}") + + add_custom_command_target( + copy_wasilibc_modulemap_resource + COMMAND + "${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir} ${module_dir_static} + COMMAND + "${CMAKE_COMMAND}" "-E" "copy_if_different" + "${CMAKE_CURRENT_SOURCE_DIR}/${wasilibc_modulemap_source}" ${module_dir} + COMMAND + "${CMAKE_COMMAND}" "-E" "copy_if_different" + "${CMAKE_CURRENT_SOURCE_DIR}/${wasilibc_modulemap_source}" ${module_dir_static} + OUTPUT ${module_dir}/${wasilibc_modulemap_source} ${module_dir_static}/${wasilibc_modulemap_source} + COMMENT "Copying WASILibc modulemap to resource directories") + add_dependencies(sdk-overlay ${copy_wasilibc_modulemap_resource}) + list(APPEND wasilibc_modulemap_target_list ${copy_wasilibc_modulemap_resource}) + + swift_install_in_component(FILES "${wasilibc_modulemap_source}" + DESTINATION "lib/swift/${arch_subdir}" + COMPONENT sdk-overlay) + if(SWIFT_BUILD_STATIC_STDLIB) + swift_install_in_component(FILES "${wasilibc_modulemap_source}" + DESTINATION "lib/swift_static/${arch_subdir}" + COMPONENT sdk-overlay) + endif() + endforeach() +endif() +add_custom_target(wasilibc_modulemap DEPENDS ${wasilibc_modulemap_target_list}) +set_property(TARGET wasilibc_modulemap PROPERTY FOLDER "Miscellaneous") +add_dependencies(sdk-overlay wasilibc_modulemap) + if(WINDOWS IN_LIST SWIFT_SDKS) swift_install_in_component(FILES ucrt.modulemap diff --git a/stdlib/public/Platform/WASILibc.swift.gyb b/stdlib/public/Platform/WASILibc.swift.gyb new file mode 100644 index 0000000000000..f3d5f2486701a --- /dev/null +++ b/stdlib/public/Platform/WASILibc.swift.gyb @@ -0,0 +1,159 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 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 +// +//===----------------------------------------------------------------------===// + +@_exported import SwiftWASILibc // Clang module + +// Constants defined by +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.") +public let M_PI = Double.pi + +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 2' or '.pi / 2' to get the value of correct type and avoid casting.") +public let M_PI_2 = Double.pi / 2 + +@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 4' or '.pi / 4' to get the value of correct type and avoid casting.") +public let M_PI_4 = Double.pi / 4 + +@available(swift, deprecated: 3.0, message: "Please use '2.squareRoot()'.") +public let M_SQRT2 = 2.squareRoot() + +@available(swift, deprecated: 3.0, message: "Please use '0.5.squareRoot()'.") +public let M_SQRT1_2 = 0.5.squareRoot() + +// Constants defined by +@available(swift, deprecated: 3.0, message: "Please use 'T.radix' to get the radix of a FloatingPoint type 'T'.") +public let FLT_RADIX = Double.radix + +%for type, prefix in [('Float', 'FLT'), ('Double', 'DBL')]: +// Where does the 1 come from? C counts the usually-implicit leading +// significand bit, but Swift does not. Neither is really right or wrong. +@available(swift, deprecated: 3.0, message: "Please use '${type}.significandBitCount + 1'.") +public let ${prefix}_MANT_DIG = ${type}.significandBitCount + 1 + +// Where does the 1 come from? C models floating-point numbers as having a +// significand in [0.5, 1), but Swift (following IEEE 754) considers the +// significand to be in [1, 2). This rationale applies to ${prefix}_MIN_EXP +// as well. +@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude.exponent + 1'.") +public let ${prefix}_MAX_EXP = ${type}.greatestFiniteMagnitude.exponent + 1 + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude.exponent + 1'.") +public let ${prefix}_MIN_EXP = ${type}.leastNormalMagnitude.exponent + 1 + +@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude' or '.greatestFiniteMagnitude'.") +public let ${prefix}_MAX = ${type}.greatestFiniteMagnitude + +@available(swift, deprecated: 3.0, message: "Please use '${type}.ulpOfOne' or '.ulpOfOne'.") +public let ${prefix}_EPSILON = ${type}.ulpOfOne + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude' or '.leastNormalMagnitude'.") +public let ${prefix}_MIN = ${type}.leastNormalMagnitude + +@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNonzeroMagnitude' or '.leastNonzeroMagnitude'.") +public let ${prefix}_TRUE_MIN = ${type}.leastNonzeroMagnitude + +%end + +public let MAP_FAILED: UnsafeMutableRawPointer! = UnsafeMutableRawPointer(bitPattern: -1) + +// NOTE: wasi-libc's error.h defines these macros as function-like macros, which ClangImporter can't import for now. +%{ +posix_error_codes = [ + "E2BIG", + "EACCES", + "EADDRINUSE", + "EADDRNOTAVAIL", + "EAFNOSUPPORT", + "EAGAIN", + "EALREADY", + "EBADF", + "EBADMSG", + "EBUSY", + "ECANCELED", + "ECHILD", + "ECONNABORTED", + "ECONNREFUSED", + "ECONNRESET", + "EDEADLK", + "EDESTADDRREQ", + "EDOM", + "EDQUOT", + "EEXIST", + "EFAULT", + "EFBIG", + "EHOSTUNREACH", + "EIDRM", + "EILSEQ", + "EINPROGRESS", + "EINTR", + "EINVAL", + "EIO", + "EISCONN", + "EISDIR", + "ELOOP", + "EMFILE", + "EMLINK", + "EMSGSIZE", + "EMULTIHOP", + "ENAMETOOLONG", + "ENETDOWN", + "ENETRESET", + "ENETUNREACH", + "ENFILE", + "ENOBUFS", + "ENODEV", + "ENOENT", + "ENOEXEC", + "ENOLCK", + "ENOLINK", + "ENOMEM", + "ENOMSG", + "ENOPROTOOPT", + "ENOSPC", + "ENOSYS", + "ENOTCONN", + "ENOTDIR", + "ENOTEMPTY", + "ENOTRECOVERABLE", + "ENOTSOCK", + "ENOTSUP", + "ENOTTY", + "ENXIO", + "EOVERFLOW", + "EOWNERDEAD", + "EPERM", + "EPIPE", + "EPROTO", + "EPROTONOSUPPORT", + "EPROTOTYPE", + "ERANGE", + "EROFS", + "ESPIPE", + "ESRCH", + "ESTALE", + "ETIMEDOUT", + "ETXTBSY", + "EXDEV", + "ENOTCAPABLE", +] +}% + +%for ecode in posix_error_codes: + +public let ${ecode} = POSIXErrorCode.${ecode}.rawValue + +%end + +// NOTE: wasi-libc's _seek.h defines these macros as function-like macros, which ClangImporter can't import for now. + +public let SEEK_SET: Int32 = 0 +public let SEEK_CUR: Int32 = 1 +public let SEEK_END: Int32 = 2 diff --git a/stdlib/public/Platform/wasi-libc.modulemap b/stdlib/public/Platform/wasi-libc.modulemap new file mode 100644 index 0000000000000..2d507670085c4 --- /dev/null +++ b/stdlib/public/Platform/wasi-libc.modulemap @@ -0,0 +1,98 @@ +//===--- wasi-libc.modulemap.gyb ------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2020 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 +// +//===----------------------------------------------------------------------===// + +module SwiftWASILibc [system] { + header "stdc-predef.h" + header "features.h" + + // C standard library + header "complex.h" + header "ctype.h" + header "errno.h" + header "fenv.h" + header "float.h" + header "inttypes.h" + header "iso646.h" + header "limits.h" + header "locale.h" + header "math.h" + header "stdarg.h" + header "stdbool.h" + header "stddef.h" + header "stdint.h" + header "stdio.h" + header "stdlib.h" + header "string.h" + header "tgmath.h" + header "time.h" + + // POSIX + header "arpa/inet.h" + header "cpio.h" + header "dirent.h" + header "fcntl.h" + header "fmtmsg.h" + header "fnmatch.h" + header "ftw.h" + header "glob.h" + header "iconv.h" + header "ifaddrs.h" + header "langinfo.h" + header "libgen.h" + header "monetary.h" + header "netinet/in.h" + header "netinet/tcp.h" + header "nl_types.h" + header "poll.h" + header "regex.h" + header "sched.h" + header "search.h" + header "semaphore.h" + header "strings.h" + header "sys/file.h" + header "sys/ioctl.h" + header "sys/select.h" + header "sys/socket.h" + header "sys/stat.h" + header "sys/time.h" + header "sys/types.h" + header "sys/uio.h" + header "sys/un.h" + header "sys/utsname.h" + header "sysexits.h" + header "tar.h" + header "unistd.h" + header "utime.h" + + // WASI specific + header "wasi/api.h" + export * +} + +module wasi_emulated_mman { + header "sys/mman.h" + link "wasi-emulated-mman" + export * +} + +module wasi_emulated_process_clock { + header "sys/times.h" + header "sys/resource.h" + link "wasi-emulated-process-clocks" + export * +} + +module wasi_emulated_signal { + header "signal.h" + link "wasi-emulated-signal" + export * +}