Skip to content

Commit 5b0a382

Browse files
author
Gabor Horvath
committed
[cxx-interop] Support SIMD types in reverse interop
This supports both built-in vector types and the SIMDX<T> Swift types that are used through type aliases like float3. These SIMD types are passed via compatibility structs (with their valued memcpy-d into the ABI compatible struct) as they have special ABI rules. E.g., a float3 is not passed as float3, but as float4 on the ABI level. Previously, we did not expose simd types from Swift to C++ (unless the SIMD types were impoted from clang). rdar://153218744
1 parent 016e55b commit 5b0a382

File tree

7 files changed

+257
-57
lines changed

7 files changed

+257
-57
lines changed

lib/IRGen/IRABIDetailsProvider.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "clang/CodeGen/ModuleBuilder.h"
3939
#include "clang/CodeGen/SwiftCallingConv.h"
4040
#include "llvm/IR/DerivedTypes.h"
41+
#include <optional>
4142

4243
using namespace swift;
4344
using namespace irgen;
@@ -59,13 +60,25 @@ getPrimitiveTypeFromLLVMType(ASTContext &ctx, const llvm::Type *type) {
5960
default:
6061
return std::nullopt;
6162
}
62-
} else if (type->isFloatTy()) {
63+
}
64+
if (type->isFloatTy()) {
6365
return ctx.getFloatType();
64-
} else if (type->isDoubleTy()) {
66+
}
67+
if (type->isDoubleTy()) {
6568
return ctx.getDoubleType();
66-
} else if (type->isPointerTy()) {
69+
}
70+
if (type->isPointerTy()) {
6771
return ctx.getOpaquePointerType();
6872
}
73+
if (const auto *vecTy = dyn_cast<llvm::VectorType>(type)) {
74+
auto elemTy = getPrimitiveTypeFromLLVMType(ctx, vecTy->getElementType());
75+
if (!elemTy)
76+
return std::nullopt;
77+
auto elemCount = vecTy->getElementCount();
78+
if (!elemCount.isFixed())
79+
return std::nullopt;
80+
return BuiltinVectorType::get(ctx, *elemTy, elemCount.getFixedValue());
81+
}
6982
// FIXME: Handle vector type.
7083
return std::nullopt;
7184
}

lib/PrintAsClang/PrimitiveTypeMapping.cpp

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@
1414
#include "swift/AST/ASTContext.h"
1515
#include "swift/AST/Decl.h"
1616
#include "swift/AST/Module.h"
17+
#include "swift/AST/Type.h"
18+
#include "swift/AST/Types.h"
1719
#include "swift/Basic/Assertions.h"
1820
#include "swift/ClangImporter/ClangImporter.h"
21+
#include <cctype>
22+
#include <optional>
23+
#include <string>
1924

2025
using namespace swift;
2126

@@ -101,13 +106,19 @@ void PrimitiveTypeMapping::initialize(ASTContext &ctx) {
101106
#define MAP_SIMD_TYPE(BASENAME, _, __) \
102107
StringRef simd2##BASENAME = "swift_" #BASENAME "2"; \
103108
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "2")}] = { \
104-
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false}; \
109+
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false, true}; \
110+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "2")}] = { \
111+
simd2##BASENAME, simd2##BASENAME, simd2##BASENAME, false, true}; \
105112
StringRef simd3##BASENAME = "swift_" #BASENAME "3"; \
106113
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "3")}] = { \
107-
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false}; \
114+
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false, true}; \
115+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "3")}] = { \
116+
simd3##BASENAME, simd3##BASENAME, simd3##BASENAME, false, true}; \
108117
StringRef simd4##BASENAME = "swift_" #BASENAME "4"; \
109118
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier(#BASENAME "4")}] = { \
110-
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false};
119+
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false, true}; \
120+
mappedTypeNames[{ctx.Id_simd, ctx.getIdentifier("simd_" #BASENAME "4")}] = { \
121+
simd4##BASENAME, simd4##BASENAME, simd4##BASENAME, false, true};
111122
#include "swift/ClangImporter/SIMDMappedTypes.def"
112123
static_assert(SWIFT_MAX_IMPORTED_SIMD_ELEMENTS == 4,
113124
"must add or remove special name mappings if max number of "
@@ -130,15 +141,17 @@ PrimitiveTypeMapping::getMappedTypeInfoOrNull(const TypeDecl *typeDecl) {
130141
std::optional<PrimitiveTypeMapping::ClangTypeInfo>
131142
PrimitiveTypeMapping::getKnownObjCTypeInfo(const TypeDecl *typeDecl) {
132143
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl))
133-
return ClangTypeInfo{typeInfo->objcName, typeInfo->canBeNullable};
144+
return ClangTypeInfo{typeInfo->objcName, typeInfo->canBeNullable,
145+
typeInfo->simd};
134146
return std::nullopt;
135147
}
136148

137149
std::optional<PrimitiveTypeMapping::ClangTypeInfo>
138150
PrimitiveTypeMapping::getKnownCTypeInfo(const TypeDecl *typeDecl) {
139151
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl)) {
140152
if (typeInfo->cName)
141-
return ClangTypeInfo{*typeInfo->cName, typeInfo->canBeNullable};
153+
return ClangTypeInfo{*typeInfo->cName, typeInfo->canBeNullable,
154+
typeInfo->simd};
142155
}
143156
return std::nullopt;
144157
}
@@ -147,7 +160,32 @@ std::optional<PrimitiveTypeMapping::ClangTypeInfo>
147160
PrimitiveTypeMapping::getKnownCxxTypeInfo(const TypeDecl *typeDecl) {
148161
if (auto *typeInfo = getMappedTypeInfoOrNull(typeDecl)) {
149162
if (typeInfo->cxxName)
150-
return ClangTypeInfo{*typeInfo->cxxName, typeInfo->canBeNullable};
163+
return ClangTypeInfo{*typeInfo->cxxName, typeInfo->canBeNullable,
164+
typeInfo->simd};
151165
}
152166
return std::nullopt;
153167
}
168+
169+
std::optional<PrimitiveTypeMapping::ClangTypeInfo>
170+
PrimitiveTypeMapping::getKnownSIMDTypeInfo(Type t, ASTContext &ctx) {
171+
auto vecTy = t->getAs<BuiltinVectorType>();
172+
if (!vecTy)
173+
return std::nullopt;
174+
175+
auto elemTy = vecTy->getElementType();
176+
auto numElems = vecTy->getNumElements();
177+
178+
if (mappedTypeNames.empty())
179+
initialize(ctx);
180+
181+
Identifier moduleName = ctx.Id_simd;
182+
std::string elemTyName = elemTy.getString();
183+
// While the element type starts with an upper case, vector types start with
184+
// lower case.
185+
elemTyName[0] = std::tolower(elemTyName[0]);
186+
Identifier name = ctx.getIdentifier(elemTyName + std::to_string(numElems));
187+
auto iter = mappedTypeNames.find({moduleName, name});
188+
if (iter == mappedTypeNames.end())
189+
return std::nullopt;
190+
return ClangTypeInfo{*iter->second.cName, false, true};
191+
}

lib/PrintAsClang/PrimitiveTypeMapping.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,21 @@ namespace swift {
2121

2222
class ASTContext;
2323
class TypeDecl;
24+
class Type;
2425

2526
/// Provides a mapping from Swift's primitive types to C / Objective-C / C++
2627
/// primitive types.
2728
///
2829
/// Certain types have mappings that differ in different language modes.
29-
/// For example, Swift's `Int` maps to `NSInteger` for Objective-C declarations,
30-
/// but to something like `intptr_t` or `swift::Int` for C and C++ declarations.
30+
/// For example, Swift's `Int` maps to `NSInteger` for Objective-C
31+
/// declarations, but to something like `intptr_t` or `swift::Int` for C and
32+
/// C++ declarations.
3133
class PrimitiveTypeMapping {
3234
public:
3335
struct ClangTypeInfo {
3436
StringRef name;
3537
bool canBeNullable;
38+
bool simd;
3639
};
3740

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

53+
std::optional<ClangTypeInfo> getKnownSIMDTypeInfo(Type t, ASTContext &ctx);
54+
5055
private:
5156
void initialize(ASTContext &ctx);
5257

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

6369
FullClangTypeInfo *getMappedTypeInfoOrNull(const TypeDecl *typeDecl);

0 commit comments

Comments
 (0)