Skip to content

Commit 1a9ae47

Browse files
Teach the importer to import any clang vector type as SIMDn<Scalar>. (swiftlang#23454)
* Teach the importer to import any vector type as SIMDN<Scalar>. Instead of having a known set of vector types, check to see if the element type conforms to SIMDScalar; if it does, see if we have a SIMDN defined with the right number of elements. If both are satisfied, import the vector type as that Swift type. By making this change, we gain the ability to import vector types that aren't defined in terms of the Darwin simd module, which lets us use C API with vector types on other platforms. It also lets us import *every* vector type that Swift can represent, rather than the small subset that are currently hardcoded. * Increased test coverage for increased SIMD types that we can import. Includes some minor cleanup from review. Also eliminates the old simd_sans_simd test, since we can now import all of these types even when the simd module isn't imported.
1 parent 20733ba commit 1a9ae47

File tree

8 files changed

+211
-86
lines changed

8 files changed

+211
-86
lines changed

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ PROTOCOL(Error)
6767
PROTOCOL_(ErrorCodeProtocol)
6868
PROTOCOL(OptionSet)
6969
PROTOCOL(CaseIterable)
70+
PROTOCOL(SIMDScalar)
7071

7172
PROTOCOL_(BridgedNSError)
7273
PROTOCOL_(BridgedStoredNSError)

lib/ClangImporter/ImportType.cpp

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -510,36 +510,36 @@ namespace {
510510
}
511511

512512
ImportResult VisitVectorType(const clang::VectorType *type) {
513-
auto *SIMD = Impl.tryLoadSIMDModule();
514-
if (!SIMD)
515-
return Type();
516-
517-
// Map the element type and count to a Swift name, such as
518-
// float x 3 => Float3.
519-
SmallString<16> name;
520-
{
521-
llvm::raw_svector_ostream names(name);
522-
523-
if (auto builtinTy
524-
= dyn_cast<clang::BuiltinType>(type->getElementType())){
525-
switch (builtinTy->getKind()) {
526-
#define MAP_SIMD_TYPE(TYPE_NAME, __, BUILTIN_KIND) \
527-
case clang::BuiltinType::BUILTIN_KIND: \
528-
names << #TYPE_NAME; \
529-
break;
530-
#include "swift/ClangImporter/SIMDMappedTypes.def"
531-
default:
532-
// A vector type we don't know how to map.
533-
return Type();
513+
// Get the imported element type and count.
514+
Type element = Impl.importTypeIgnoreIUO(
515+
type->getElementType(), ImportTypeKind::Abstract,
516+
false /* No NSUIntegerAsInt */, Bridgeability::None,
517+
OptionalTypeKind::OTK_None);
518+
unsigned count = type->getNumElements();
519+
// Import vector-of-one as the element type.
520+
if (count == 1) { return element; }
521+
// Imported element type needs to conform to SIMDScalar.
522+
auto nominal = element->getAnyNominal();
523+
auto simdscalar = Impl.SwiftContext.getProtocol(KnownProtocolKind::SIMDScalar);
524+
SmallVector<ProtocolConformance *, 2> conformances;
525+
if (simdscalar && nominal->lookupConformance(nominal->getParentModule(),
526+
simdscalar, conformances)) {
527+
// Element type conforms to SIMDScalar. Get the SIMDn generic type
528+
// if it exists.
529+
SmallString<8> name("SIMD");
530+
name.append(std::to_string(count));
531+
if (auto vector = Impl.getNamedSwiftType(Impl.getStdlibModule(), name)) {
532+
if (auto unbound = vector->getAs<UnboundGenericType>()) {
533+
// All checks passed: the imported element type is SIMDScalar,
534+
// and a generic SIMDn type exists with n == count. Construct the
535+
// bound generic type and return that.
536+
return BoundGenericType::get(
537+
cast<NominalTypeDecl>(unbound->getDecl()), Type(), { element }
538+
);
534539
}
535-
} else {
536-
return Type();
537540
}
538-
539-
names << type->getNumElements();
540541
}
541-
542-
return Impl.getNamedSwiftType(SIMD, name);
542+
return Type();
543543
}
544544

545545
ImportResult VisitFunctionProtoType(const clang::FunctionProtoType *type) {
@@ -2326,11 +2326,6 @@ ModuleDecl *ClangImporter::Implementation::tryLoadFoundationModule() {
23262326
ImportForwardDeclarations, checkedModules);
23272327
}
23282328

2329-
ModuleDecl *ClangImporter::Implementation::tryLoadSIMDModule() {
2330-
return tryLoadModule(SwiftContext, SwiftContext.Id_simd,
2331-
ImportForwardDeclarations, checkedModules);
2332-
}
2333-
23342329
Type ClangImporter::Implementation::getNamedSwiftType(ModuleDecl *module,
23352330
StringRef name) {
23362331
if (!module)

lib/ClangImporter/ImporterImpl.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -888,12 +888,6 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
888888
/// into the ASTContext.
889889
ModuleDecl *tryLoadFoundationModule();
890890

891-
/// Returns the "SIMD" module, if it can be loaded.
892-
///
893-
/// After this has been called, the SIMD module will or won't be loaded
894-
/// into the ASTContext.
895-
ModuleDecl *tryLoadSIMDModule();
896-
897891
/// Retrieves the Swift wrapper for the given Clang module, creating
898892
/// it if necessary.
899893
ClangModuleUnit *getWrapperForModule(const clang::Module *underlying);

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
41094109
case KnownProtocolKind::Hashable:
41104110
case KnownProtocolKind::CaseIterable:
41114111
case KnownProtocolKind::Comparable:
4112+
case KnownProtocolKind::SIMDScalar:
41124113
case KnownProtocolKind::ObjectiveCBridgeable:
41134114
case KnownProtocolKind::DestructorSafeContainer:
41144115
case KnownProtocolKind::SwiftNewtypeWrapper:

stdlib/public/Darwin/simd/simd.swift.gyb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,19 @@ public extension SIMD where Scalar : FixedWidthInteger {
4444
component = ['x','y','z','w']
4545
scalar_types = ['Float','Double','Int32','UInt32']
4646
ctype = { 'Float':'float', 'Double':'double', 'Int32':'int', 'UInt32':'uint'}
47-
llvm_type = { 'Float':'FPIEEE32', 'Double':'FPIEEE64', 'Int32':'Int32', 'UInt32':'Int32' }
4847
floating_types = ['Float','Double']
49-
cardinal = { 2:'two', 3:'three', 4:'four'}
5048
}%
5149

5250
%for scalar in scalar_types:
5351
% for count in [2, 3, 4]:
5452
% vectype = ctype[scalar] + str(count)
55-
% llvm_vectype = "Vec" + str(count) + "x" + llvm_type[scalar]
5653
% vecsize = (8 if scalar == 'Double' else 4) * (4 if count == 3 else count)
5754
% vecalign = (16 if vecsize > 16 else vecsize)
58-
% extractelement = "extractelement_" + llvm_vectype + "_Int32"
59-
% insertelement = "insertelement_" + llvm_vectype + "_" + llvm_type[scalar] + "_Int32"
6055
% is_floating = scalar in floating_types
6156
% is_signed = scalar[0] != 'U'
6257
% wrap = "" if is_floating else "&"
6358
59+
@available(swift, deprecated: 5.1, message: "Use SIMD${count}<${scalar}>")
6460
public typealias ${vectype} = SIMD${count}<${scalar}>
6561
6662
% if is_signed:

test/ClangImporter/simd.swift

Lines changed: 72 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,79 @@
11
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -module-name main -typecheck -verify %s
22

33
import c_simd
4-
import simd
54

6-
let f4: float4 = makes_float4()
7-
let i3: int3 = makes_int3()
8-
let d2: double2 = makes_double2()
9-
let u4: uint4 = makes_uint4()
5+
let char2_value: char2 = makes_char2()
6+
let char64_value: char64 = makes_char64()
7+
let uchar3_value: uchar3 = makes_uchar3()
8+
let uchar32_value: uchar32 = makes_uchar32()
9+
let short3_value: short3 = makes_short3()
10+
let short8_value: short8 = makes_short8()
11+
let ushort1_value: ushort1 = makes_ushort1()
12+
let ushort16_value: ushort16 = makes_ushort16()
13+
let int3_value: int3 = makes_int3()
14+
let int32_value: int32 = makes_int32()
15+
let uint4_value: uint4 = makes_uint4()
16+
let uint2_value: uint2 = makes_uint2()
17+
let long2_value: long2 = makes_long2()
18+
let long8_value: long8 = makes_long8()
19+
let ulong4_value: ulong4 = makes_ulong4()
20+
let ulong1_value: ulong1 = makes_ulong1()
21+
let ll3_value: ll3 = makes_ll3()
22+
let ll8_value: ll8 = makes_ll8()
23+
let ull4_value: ull4 = makes_ull4()
24+
let ull16_value: ull16 = makes_ull16()
25+
let float2_value: float2 = makes_float2()
26+
let float3_value: float3 = makes_float3()
27+
let float4_value: float4 = makes_float4()
28+
let float8_value: float8 = makes_float8()
29+
let float16_value: float16 = makes_float16()
30+
let double2_value: double2 = makes_double2()
31+
let double3_value: double3 = makes_double3()
32+
let double4_value: double4 = makes_double4()
33+
let double8_value: double8 = makes_double8()
1034

11-
takes_float4(f4)
12-
takes_int3(i3)
13-
takes_double2(d2)
14-
takes_uint4(u4)
35+
takes_char2(char2_value)
36+
takes_char64(char64_value)
37+
takes_uchar3(uchar3_value)
38+
takes_uchar32(uchar32_value)
39+
takes_short3(short3_value)
40+
takes_short8(short8_value)
41+
takes_ushort1(ushort1_value)
42+
takes_ushort16(ushort16_value)
43+
takes_int3(int3_value)
44+
takes_int32(int32_value)
45+
takes_uint4(uint4_value)
46+
takes_uint2(uint2_value)
47+
takes_long2(long2_value)
48+
takes_long8(long8_value)
49+
takes_ulong4(ulong4_value)
50+
takes_ulong1(ulong1_value)
51+
takes_ll3(ll3_value)
52+
takes_ll8(ll8_value)
53+
takes_ull4(ull4_value)
54+
takes_ull16(ull16_value)
55+
takes_float2(float2_value)
56+
takes_float3(float3_value)
57+
takes_float4(float4_value)
58+
takes_float8(float8_value)
59+
takes_float16(float16_value)
60+
takes_double2(double2_value)
61+
takes_double3(double3_value)
62+
takes_double4(double4_value)
63+
takes_double8(double8_value)
1564

16-
// byte17 isn't available since there isn't a type in the simd module to map it to.
65+
// These shouldn't be imported, since there's no type to map them to.
1766

18-
let b17 = makes_byte17 // expected-error{{unresolved identifier 'makes_byte17'}}
19-
takes_byte17(b17) // expected-error{{unresolved identifier 'takes_byte17'}}
67+
let char17_value = makes_char17() // expected-error{{unresolved identifier 'makes_char17'}}
68+
let uchar21_value = makes_uchar21() // expected-error{{unresolved identifier 'makes_uchar21'}}
69+
let short5_value = makes_short5() // expected-error{{unresolved identifier 'makes_short5'}}
70+
let ushort6_value = makes_ushort6() // expected-error{{unresolved identifier 'makes_ushort6'}}
71+
let int128_value = makes_int128() // expected-error{{unresolved identifier 'makes_int128'}}
72+
let uint20_value = makes_uint20() // expected-error{{unresolved identifier 'makes_uint20'}}
73+
74+
takes_char17(char17_value) // expected-error{{unresolved identifier 'takes_char17'}}
75+
takes_uchar21(uchar21_value) // expected-error{{unresolved identifier 'takes_uchar21'}}
76+
takes_short5(short5_value) // expected-error{{unresolved identifier 'takes_short5'}}
77+
takes_ushort6(ushort6_value) // expected-error{{unresolved identifier 'takes_ushort6'}}
78+
takes_int128(int128_value) // expected-error{{unresolved identifier 'takes_int128'}}
79+
takes_uint20(uint20_value) // expected-error{{unresolved identifier 'takes_uint20'}}

test/ClangImporter/simd_sans_simd.swift

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 109 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,111 @@
1-
typedef int int3 __attribute__((__ext_vector_type__(3)));
2-
typedef float float3 __attribute__((__ext_vector_type__(3)));
3-
typedef float float4 __attribute__((__ext_vector_type__(4)));
4-
typedef double double2 __attribute__((__ext_vector_type__(2)));
5-
typedef unsigned int uint4 __attribute__((__ext_vector_type__(4)));
6-
typedef unsigned char byte17 __attribute__((__ext_vector_type__(17)));
1+
// Types that we should be able to import.
2+
typedef char __attribute__((ext_vector_type(2))) char2;
3+
typedef char __attribute__((ext_vector_type(64))) char64;
4+
typedef unsigned char __attribute__((ext_vector_type(3))) uchar3;
5+
typedef unsigned char __attribute__((ext_vector_type(32))) uchar32;
6+
typedef short __attribute__((ext_vector_type(3))) short3;
7+
typedef short __attribute__((ext_vector_type(8))) short8;
8+
typedef unsigned short __attribute__((ext_vector_type(1))) ushort1;
9+
typedef unsigned short __attribute__((ext_vector_type(16))) ushort16;
10+
typedef int __attribute__((ext_vector_type(3))) int3;
11+
typedef int __attribute__((ext_vector_type(32))) int32;
12+
typedef unsigned int __attribute__((ext_vector_type(4))) uint4;
13+
typedef unsigned int __attribute__((ext_vector_type(2))) uint2;
14+
typedef long __attribute__((ext_vector_type(2))) long2;
15+
typedef long __attribute__((ext_vector_type(8))) long8;
16+
typedef unsigned long __attribute__((ext_vector_type(4))) ulong4;
17+
typedef unsigned long __attribute__((ext_vector_type(1))) ulong1;
18+
typedef long long __attribute__((ext_vector_type(3))) ll3;
19+
typedef long long __attribute__((ext_vector_type(8))) ll8;
20+
typedef unsigned long long __attribute__((ext_vector_type(4))) ull4;
21+
typedef unsigned long long __attribute__((ext_vector_type(16))) ull16;
722

8-
int3 makes_int3(void);
9-
uint4 makes_uint4(void);
10-
float3 makes_float3(void);
11-
float4 makes_float4(void);
12-
double2 makes_double2(void);
13-
byte17 makes_byte17(void);
23+
typedef float __attribute__((ext_vector_type(2))) float2;
24+
typedef float __attribute__((ext_vector_type(3))) float3;
25+
typedef float __attribute__((ext_vector_type(4))) float4;
26+
typedef float __attribute__((ext_vector_type(8))) float8;
27+
typedef float __attribute__((ext_vector_type(16))) float16;
28+
typedef double __attribute__((ext_vector_type(2))) double2;
29+
typedef double __attribute__((ext_vector_type(3))) double3;
30+
typedef double __attribute__((ext_vector_type(4))) double4;
31+
typedef double __attribute__((ext_vector_type(8))) double8;
1432

15-
void takes_int3(int3 x);
16-
void takes_uint4(uint4 x);
17-
void takes_float3(float3 x);
18-
void takes_float4(float4 x);
19-
void takes_double2(double2 x);
20-
void takes_byte17(byte17 x);
33+
// Types that we should not be able to import.
34+
typedef char __attribute__((ext_vector_type(17))) char17;
35+
typedef unsigned char __attribute__((ext_vector_type(21))) uchar21;
36+
typedef short __attribute__((ext_vector_type(5))) short5;
37+
typedef unsigned short __attribute__((ext_vector_type(6))) ushort6;
38+
typedef int __attribute__((ext_vector_type(128))) int128;
39+
typedef unsigned int __attribute__((ext_vector_type(20))) uint20;
40+
41+
char2 makes_char2();
42+
char64 makes_char64();
43+
uchar3 makes_uchar3();
44+
uchar32 makes_uchar32();
45+
short3 makes_short3();
46+
short8 makes_short8();
47+
ushort1 makes_ushort1();
48+
ushort16 makes_ushort16();
49+
int3 makes_int3();
50+
int32 makes_int32();
51+
uint4 makes_uint4();
52+
uint2 makes_uint2();
53+
long2 makes_long2();
54+
long8 makes_long8();
55+
ulong4 makes_ulong4();
56+
ulong1 makes_ulong1();
57+
ll3 makes_ll3();
58+
ll8 makes_ll8();
59+
ull4 makes_ull4();
60+
ull16 makes_ull16();
61+
float2 makes_float2();
62+
float3 makes_float3();
63+
float4 makes_float4();
64+
float8 makes_float8();
65+
float16 makes_float16();
66+
double2 makes_double2();
67+
double3 makes_double3();
68+
double4 makes_double4();
69+
double8 makes_double8();
70+
char17 makes_char17();
71+
uchar21 makes_uchar21();
72+
short5 makes_short5();
73+
ushort6 makes_ushort6();
74+
int128 makes_int128();
75+
uint20 makes_uint20();
76+
77+
takes_char2(char2);
78+
takes_char64(char64);
79+
takes_uchar3(uchar3);
80+
takes_uchar32(uchar32);
81+
takes_short3(short3);
82+
takes_short8(short8);
83+
takes_ushort1(ushort1);
84+
takes_ushort16(ushort16);
85+
takes_int3(int3);
86+
takes_int32(int32);
87+
takes_uint4(uint4);
88+
takes_uint2(uint2);
89+
takes_long2(long2);
90+
takes_long8(long8);
91+
takes_ulong4(ulong4);
92+
takes_ulong1(ulong1);
93+
takes_ll3(ll3);
94+
takes_ll8(ll8);
95+
takes_ull4(ull4);
96+
takes_ull16(ull16);
97+
takes_float2(float2);
98+
takes_float3(float3);
99+
takes_float4(float4);
100+
takes_float8(float8);
101+
takes_float16(float16);
102+
takes_double2(double2);
103+
takes_double3(double3);
104+
takes_double4(double4);
105+
takes_double8(double8);
106+
takes_char17(char17);
107+
takes_uchar21(uchar21);
108+
takes_short5(short5);
109+
takes_ushort6(ushort6);
110+
takes_int128(int128);
111+
takes_uint20(uint20);

0 commit comments

Comments
 (0)