Skip to content

[cxx-interop] Support SIMD types in reverse interop #83586

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
20 changes: 16 additions & 4 deletions lib/IRGen/IRABIDetailsProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/CodeGen/SwiftCallingConv.h"
#include "llvm/IR/DerivedTypes.h"
#include <optional>

using namespace swift;
using namespace irgen;
Expand All @@ -59,14 +60,25 @@ getPrimitiveTypeFromLLVMType(ASTContext &ctx, const llvm::Type *type) {
default:
return std::nullopt;
}
} else if (type->isFloatTy()) {
}
if (type->isFloatTy()) {
return ctx.getFloatType();
} else if (type->isDoubleTy()) {
}
if (type->isDoubleTy()) {
return ctx.getDoubleType();
} else if (type->isPointerTy()) {
}
if (type->isPointerTy()) {
return ctx.getOpaquePointerType();
}
// FIXME: Handle vector type.
if (const auto *vecTy = dyn_cast<llvm::VectorType>(type)) {
auto elemTy = getPrimitiveTypeFromLLVMType(ctx, vecTy->getElementType());
if (!elemTy)
return std::nullopt;
auto elemCount = vecTy->getElementCount();
if (!elemCount.isFixed())
return std::nullopt;
return BuiltinVectorType::get(ctx, *elemTy, elemCount.getFixedValue());
}
return std::nullopt;
}

Expand Down
50 changes: 44 additions & 6 deletions lib/PrintAsClang/PrimitiveTypeMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Module.h"
#include "swift/AST/Type.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Assertions.h"
#include "swift/ClangImporter/ClangImporter.h"
#include <cctype>
#include <optional>
#include <string>

using namespace swift;

Expand Down Expand Up @@ -101,13 +106,19 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
#define MAP_SIMD_TYPE(BASENAME, _, __) \
StringRef simd2##BASENAME = "swift_" #BASENAME "2"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] = { \
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false}; \
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false, true}; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "2")}] = { \
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false, true}; \
StringRef simd3##BASENAME = "swift_" #BASENAME "3"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] = { \
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false}; \
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false, true}; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "3")}] = { \
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false, true}; \
StringRef simd4##BASENAME = "swift_" #BASENAME "4"; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] = { \
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false};
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false, true}; \
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "4")}] = { \
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false, true};
#include "swift/ClangImporter/SIMDMappedTypes.def"
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
"must add or remove special name mappings if max number of "
Expand All @@ -130,15 +141,17 @@ PrimitiveTypeMapping::getMappedTypeInfoOrNull(const TypeDecl *typeDecl) {
std::optional<PrimitiveTypeMapping::ClangTypeInfo>
PrimitiveTypeMapping::getKnownObjCTypeInfo(const TypeDecl *typeDecl) {
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl))
return ClangTypeInfo{typeInfo->objcName, typeInfo->canBeNullable};
return ClangTypeInfo{typeInfo->objcName, typeInfo->canBeNullable,
typeInfo->simd};
return std::nullopt;
}

std::optional<PrimitiveTypeMapping::ClangTypeInfo>
PrimitiveTypeMapping::getKnownCTypeInfo(const TypeDecl *typeDecl) {
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl)) {
if (typeInfo->cName)
return ClangTypeInfo{*typeInfo->cName, typeInfo->canBeNullable};
return ClangTypeInfo{*typeInfo->cName, typeInfo->canBeNullable,
typeInfo->simd};
}
return std::nullopt;
}
Expand All @@ -147,7 +160,32 @@ std::optional<PrimitiveTypeMapping::ClangTypeInfo>
PrimitiveTypeMapping::getKnownCxxTypeInfo(const TypeDecl *typeDecl) {
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl)) {
if (typeInfo->cxxName)
return ClangTypeInfo{*typeInfo->cxxName, typeInfo->canBeNullable};
return ClangTypeInfo{*typeInfo->cxxName, typeInfo->canBeNullable,
typeInfo->simd};
}
return std::nullopt;
}

std::optional<PrimitiveTypeMapping::ClangTypeInfo>
PrimitiveTypeMapping::getKnownSIMDTypeInfo(Type t, ASTContext &ctx) {
auto vecTy = t->getAs<BuiltinVectorType>();
if (!vecTy)
return std::nullopt;

auto elemTy = vecTy->getElementType();
auto numElems = vecTy->getNumElements();

if (mappedTypeNames.empty())
initialize(ctx);

Identifier moduleName = ctx.Id_simd;
std::string elemTyName = elemTy.getString();
// While the element type starts with an upper case, vector types start with
// lower case.
elemTyName[0] = std::tolower(elemTyName[0]);
Identifier name = ctx.getIdentifier(elemTyName + std::to_string(numElems));
auto iter = mappedTypeNames.find({moduleName, name});
if (iter == mappedTypeNames.end())
return std::nullopt;
return ClangTypeInfo{*iter->second.cName, false, true};
}
10 changes: 8 additions & 2 deletions lib/PrintAsClang/PrimitiveTypeMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ namespace swift {

class ASTContext;
class TypeDecl;
class Type;

/// Provides a mapping from Swift's primitive types to C / Objective-C / C++
/// primitive types.
///
/// Certain types have mappings that differ in different language modes.
/// For example, Swift's `Int` maps to `NSInteger` for Objective-C declarations,
/// but to something like `intptr_t` or `swift::Int` for C and C++ declarations.
/// For example, Swift's `Int` maps to `NSInteger` for Objective-C
/// declarations, but to something like `intptr_t` or `swift::Int` for C and
/// C++ declarations.
class PrimitiveTypeMapping {
public:
struct ClangTypeInfo {
StringRef name;
bool canBeNullable;
bool simd;
};

/// Returns the Objective-C type name and nullability for the given Swift
Expand All @@ -47,6 +50,8 @@ class PrimitiveTypeMapping {
/// primitive type declaration, or \c None if no such type name exists.
std::optional<ClangTypeInfo> getKnownCxxTypeInfo(const TypeDecl *typeDecl);

std::optional<ClangTypeInfo> getKnownSIMDTypeInfo(Type t, ASTContext &ctx);

private:
void initialize(ASTContext &ctx);

Expand All @@ -58,6 +63,7 @@ class PrimitiveTypeMapping {
// The C++ name of the Swift type.
std::optional<StringRef> cxxName;
bool canBeNullable;
bool simd = false;
};

FullClangTypeInfo *getMappedTypeInfoOrNull(const TypeDecl *typeDecl);
Expand Down
Loading