Skip to content

[cxx-interop] Add CxxShim library; move __swift_interopStaticCast into it. #59754

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

Merged
merged 2 commits into from
Jul 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 71 additions & 4 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,66 @@ ClangImporter::~ClangImporter() {

#pragma mark Module loading

static Optional<StringRef> getModuleMapFilePath(StringRef name,
SearchPathOptions &Opts,
llvm::Triple triple,
SmallVectorImpl<char> &buffer) {
StringRef platform = swift::getPlatformNameForTriple(triple);
StringRef arch = swift::getMajorArchitectureName(triple);

StringRef SDKPath = Opts.getSDKPath();
if (!SDKPath.empty()) {
buffer.clear();
buffer.append(SDKPath.begin(), SDKPath.end());
llvm::sys::path::append(buffer, "usr", "lib", "swift");
llvm::sys::path::append(buffer, platform, arch, name);

// Only specify the module map if that file actually exists. It may not;
// for example in the case that `swiftc -target x86_64-unknown-linux-gnu
// -emit-ir` is invoked using a Swift compiler not built for Linux targets.
if (llvm::sys::fs::exists(buffer))
return StringRef(buffer.data(), buffer.size());
}

if (!Opts.RuntimeResourcePath.empty()) {
buffer.clear();
buffer.append(Opts.RuntimeResourcePath.begin(),
Opts.RuntimeResourcePath.end());
llvm::sys::path::append(buffer, platform, arch, name);

// Only specify the module map if that file actually exists. It may not;
// for example in the case that `swiftc -target x86_64-unknown-linux-gnu
// -emit-ir` is invoked using a Swift compiler not built for Linux targets.
if (llvm::sys::fs::exists(buffer))
return StringRef(buffer.data(), buffer.size());
}

return None;
}

/// 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 Optional<StringRef>
getGlibcModuleMapPath(SearchPathOptions &Opts, llvm::Triple triple,
SmallVectorImpl<char> &buffer) {
return getModuleMapFilePath("glibc.modulemap", Opts, triple, buffer);
}

static Optional<StringRef>
getLibStdCxxModuleMapPath(SearchPathOptions &opts, llvm::Triple triple,
SmallVectorImpl<char> &buffer) {
return getModuleMapFilePath("libstdcxx.modulemap", opts, triple, buffer);
}

static Optional<StringRef>
getLibShimCxxModuleMapPath(SearchPathOptions &Opts, llvm::Triple triple,
SmallVectorImpl<char> &buffer) {
return getModuleMapFilePath("libcxxshim.modulemap", Opts, triple, buffer);
}

static bool clangSupportsPragmaAttributeWithSwiftAttr() {
clang::AttributeCommonInfo swiftAttrInfo(clang::SourceRange(),
clang::AttributeCommonInfo::AT_SwiftAttr,
Expand Down Expand Up @@ -553,6 +613,11 @@ importer::getNormalInvocationArguments(
});
}

SmallString<128> buffer;
if (auto path = getLibShimCxxModuleMapPath(searchPathOpts, triple, buffer)) {
invocationArgStrs.push_back((Twine("-fmodule-map-file=") + *path).str());
}

// Set C language options.
if (triple.isOSDarwin()) {
invocationArgStrs.insert(invocationArgStrs.end(), {
Expand Down Expand Up @@ -4387,10 +4452,12 @@ DeclRefExpr *getInteropStaticCastDeclRefExpr(ASTContext &ctx,
derived = derived->wrapInPointer(PTK_UnsafePointer);
}

// Lookup our static cast helper function.
// TODO: change this to stdlib or something.
auto wrapperModule =
ctx.getClangModuleLoader()->getWrapperForModule(owningModule);
// Lookup our static cast helper function in the C++ shim module.
auto wrapperModule = ctx.getLoadedModule(ctx.getIdentifier("CxxShim"));
assert(wrapperModule &&
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll make this a diagnostic in a follow-up patch.

"CxxShim module is required when using members of a base class. "
"Make sure you `import CxxShim`.");

SmallVector<ValueDecl *, 1> results;
ctx.lookupInModule(wrapperModule, "__swift_interopStaticCast", results);
assert(
Expand Down
1 change: 1 addition & 0 deletions stdlib/public/Cxx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ add_swift_target_library(swiftCxx ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVE
INSTALL_IN_COMPONENT sdk-overlay)

add_subdirectory(std)
add_subdirectory(cxxshim)
94 changes: 94 additions & 0 deletions stdlib/public/Cxx/cxxshim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
is_sdk_requested(WINDOWS swift_build_windows)
set(libcxxshim_modulemap_target_list)
foreach(sdk ${SWIFT_SDKS})
if(swift_build_windows)
continue()
endif()

foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
set(arch_suffix "${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}")
set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")

set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}")
set(module_dir_static "${SWIFTSTATICLIB_DIR}/${arch_subdir}")

set(libcxxshim_header "libcxxshim.h")
set(libcxxshim_header_out "${module_dir}/libcxxshim.h")
set(libcxxshim_header_out_static "${module_dir_static}/libcxxshim.h")
set(libcxxshim_modulemap "libcxxshim.modulemap")
set(libcxxshim_modulemap_out "${module_dir}/libcxxshim.modulemap")
set(libcxxshim_modulemap_out_static "${module_dir_static}/libcxxshim.modulemap")

add_custom_command_target(
copy_libcxxshim_modulemap
COMMAND
"${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir}
COMMAND
"${CMAKE_COMMAND}" "-E" "copy_if_different" "${CMAKE_CURRENT_SOURCE_DIR}/${libcxxshim_modulemap}" "${libcxxshim_modulemap_out}"
OUTPUT ${libcxxshim_modulemap_out}
DEPENDS ${libcxxshim_modulemap}
COMMENT "Copying libcxxshim modulemap to resources")
list(APPEND libcxxshim_modulemap_target_list ${copy_libcxxshim_modulemap})
add_dependencies(swift-stdlib-${arch_suffix} ${copy_libcxxshim_modulemap})

add_custom_command_target(
copy_libcxxshim_header
COMMAND
"${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir}
COMMAND
"${CMAKE_COMMAND}" "-E" "copy_if_different" "${CMAKE_CURRENT_SOURCE_DIR}/${libcxxshim_header}" "${libcxxshim_header_out}"
OUTPUT ${libcxxshim_header_out}
DEPENDS ${libcxxshim_header}
COMMENT "Copying libcxxshim header to resources")
list(APPEND libcxxshim_modulemap_target_list ${copy_libcxxshim_header})
add_dependencies(swift-stdlib-${arch_suffix} ${copy_libcxxshim_header})

if(SWIFT_BUILD_STATIC_STDLIB)
add_custom_command_target(
copy_libcxxshim_modulemap_static
COMMAND
"${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir_static}
COMMAND
"${CMAKE_COMMAND}" "-E" "copy_if_different"
"${libcxxshim_modulemap_out}" "${libcxxshim_modulemap_out_static}"
OUTPUT ${libcxxshim_modulemap_out_static}
DEPENDS ${copy_libcxxshim_modulemap}
COMMENT "Copying libcxxshim modulemap to static resources")
list(APPEND libcxxshim_modulemap_target_list ${copy_libcxxshim_modulemap_static})
add_dependencies(swift-stdlib-${arch_suffix} ${copy_libcxxshim_modulemap_static})

add_custom_command_target(
copy_libcxxshim_header_static
COMMAND
"${CMAKE_COMMAND}" "-E" "make_directory" ${module_dir_static}
COMMAND
"${CMAKE_COMMAND}" "-E" "copy_if_different"
"${libcxxshim_header_out}" "${libcxxshim_header_out_static}"
OUTPUT ${libcxxshim_header_out_static}
DEPENDS ${copy_libcxxshim_header}
COMMENT "Copying libcxxshim header to static resources")
list(APPEND libcxxshim_modulemap_target_list ${copy_libcxxshim_header_static})
add_dependencies(swift-stdlib-${arch_suffix} ${copy_libcxxshim_header_static})
endif()

swift_install_in_component(FILES "${libcxxshim_modulemap_out}"
DESTINATION "lib/swift/${arch_subdir}"
COMPONENT sdk-overlay)
swift_install_in_component(FILES "${libcxxshim_header_out}"
DESTINATION "lib/swift/${arch_subdir}"
COMPONENT sdk-overlay)

if(SWIFT_BUILD_STATIC_STDLIB)
swift_install_in_component(FILES "${libcxxshim_modulemap_out_static}"
DESTINATION "lib/swift_static/${arch_subdir}"
COMPONENT sdk-overlay)
swift_install_in_component(FILES "${libcxxshim_header_out_static}"
DESTINATION "lib/swift_static/${arch_subdir}"
COMPONENT sdk-overlay)
endif()
endforeach()
endforeach()

add_custom_target(libcxxshim-modulemap DEPENDS ${libcxxshim_modulemap_target_list})
set_property(TARGET libcxxshim-modulemap PROPERTY FOLDER "Miscellaneous")
add_dependencies(sdk-overlay libcxxshim-modulemap)
2 changes: 2 additions & 0 deletions stdlib/public/Cxx/cxxshim/libcxxshim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
template <class From, class To>
To __swift_interopStaticCast(From from) { return static_cast<To>(from); }
4 changes: 4 additions & 0 deletions stdlib/public/Cxx/cxxshim/libcxxshim.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module CxxShim {
header "libcxxshim.h"
requires cplusplus
}
1 change: 1 addition & 0 deletions stdlib/public/Cxx/cxxshim/libcxxshim.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@_exported import CxxShim // Clang module
Copy link
Contributor

Choose a reason for hiding this comment

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

This file is not used anymore, it can be removed.

3 changes: 0 additions & 3 deletions test/Interop/Cxx/class/inheritance/Inputs/fields.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
template <class From, class To>
To __swift_interopStaticCast(From from) { return from; }

struct HasThreeFields {
int a = 1;
int b = 2;
Expand Down
5 changes: 0 additions & 5 deletions test/Interop/Cxx/class/inheritance/Inputs/functions.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
template <class From, class To>
To __swift_interopStaticCast(From from) {
return static_cast<To>(from);
}

struct NonTrivial {
NonTrivial() {}
~NonTrivial() {}
Expand Down
5 changes: 0 additions & 5 deletions test/Interop/Cxx/class/inheritance/Inputs/type-aliases.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
template <class From, class To>
To __swift_interopStaticCast(From from) {
return static_cast<To>(from);
}

struct Base {
struct Struct {};

Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/class/inheritance/fields.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// UNSUPPORTED: OS=windows-msvc

import StdlibUnittest
import CxxShim
import Fields

var FieldsTestSuite = TestSuite("Getting and setting fields in base classes")
Expand Down
3 changes: 3 additions & 0 deletions test/Interop/Cxx/class/inheritance/functions.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop)
//
// REQUIRES: executable_test
// TODO: Fix CxxShim for Windows.
// XFAIL: OS=windows-msvc

import StdlibUnittest
import CxxShim
import Functions

var FunctionsTestSuite = TestSuite("Calling functions in base classes")
Expand Down
3 changes: 0 additions & 3 deletions test/Interop/Cxx/foreign-reference/Inputs/pod.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ inline void *operator new(size_t, void *p) { return p; }

#include "visibility.h"

template <class From, class To>
To __swift_interopStaticCast(From from) { return from; }

SWIFT_BEGIN_NULLABILITY_ANNOTATIONS

struct __attribute__((swift_attr("import_as_ref"))) Empty {
Expand Down
1 change: 1 addition & 0 deletions test/Interop/Cxx/foreign-reference/pod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// XFAIL: OS=windows-msvc

import StdlibUnittest
import CxxShim
import POD

struct StructHoldingPair {
Expand Down
3 changes: 0 additions & 3 deletions test/Interop/Cxx/operators/Inputs/member-inline.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#ifndef TEST_INTEROP_CXX_OPERATORS_INPUTS_MEMBER_INLINE_H
#define TEST_INTEROP_CXX_OPERATORS_INPUTS_MEMBER_INLINE_H

template <class From, class To>
To __swift_interopStaticCast(From from) { return from; }

struct LoadableIntWrapper {
int value;
LoadableIntWrapper operator-(LoadableIntWrapper rhs) {
Expand Down
5 changes: 4 additions & 1 deletion test/Interop/Cxx/operators/member-inline.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop)

//
// REQUIRES: executable_test
// TODO: Fix CxxShim for Windows.
// XFAIL: OS=windows-msvc

import MemberInline
import CxxShim
import StdlibUnittest

var OperatorsTestSuite = TestSuite("Operators")
Expand Down