@@ -1117,16 +1117,16 @@ namespace {
1117
1117
class OpaqueStorageTypeInfo final :
1118
1118
public ScalarTypeInfo<OpaqueStorageTypeInfo, LoadableTypeInfo>
1119
1119
{
1120
- llvm::IntegerType *ScalarType ;
1120
+ std::vector< llvm::IntegerType *> ScalarTypes ;
1121
1121
public:
1122
1122
OpaqueStorageTypeInfo (llvm::ArrayType *storage,
1123
- llvm::IntegerType *scalarType ,
1123
+ std::vector< llvm::IntegerType *> &&scalarTypes ,
1124
1124
Size size,
1125
1125
SpareBitVector &&spareBits,
1126
1126
Alignment align)
1127
1127
: ScalarTypeInfo(storage, size, std::move(spareBits), align, IsPOD,
1128
1128
IsFixedSize),
1129
- ScalarType (scalarType )
1129
+ ScalarTypes (std::move(scalarTypes) )
1130
1130
{}
1131
1131
1132
1132
llvm::ArrayType *getStorageType () const {
@@ -1139,7 +1139,7 @@ namespace {
1139
1139
}
1140
1140
1141
1141
unsigned getExplosionSize () const override {
1142
- return 1 ;
1142
+ return ScalarTypes. size () ;
1143
1143
}
1144
1144
1145
1145
void loadAsCopy (IRGenFunction &IGF, Address addr,
@@ -1149,8 +1149,18 @@ namespace {
1149
1149
1150
1150
void loadAsTake (IRGenFunction &IGF, Address addr,
1151
1151
Explosion &explosion) const override {
1152
- addr = IGF.Builder .CreateElementBitCast (addr, ScalarType);
1153
- explosion.add (IGF.Builder .CreateLoad (addr));
1152
+ auto index = ScalarTypes.size ();
1153
+ for (auto scalarTy : ScalarTypes) {
1154
+ addr = IGF.Builder .CreateElementBitCast (addr, scalarTy);
1155
+ explosion.add (IGF.Builder .CreateLoad (addr));
1156
+ --index;
1157
+ // Advance to next scalar chunk.
1158
+ if (index > 0 ) {
1159
+ addr = IGF.Builder .CreateElementBitCast (addr, IGF.IGM .Int8Ty );
1160
+ auto currentScalarTypeSize = Size (scalarTy->getIntegerBitWidth ()/8 );
1161
+ addr = IGF.Builder .CreateConstByteArrayGEP (addr, currentScalarTypeSize);
1162
+ }
1163
+ }
1154
1164
}
1155
1165
1156
1166
void assign (IRGenFunction &IGF, Explosion &explosion, Address addr,
@@ -1160,13 +1170,26 @@ namespace {
1160
1170
1161
1171
void initialize (IRGenFunction &IGF, Explosion &explosion, Address addr,
1162
1172
bool isOutlined) const override {
1163
- addr = IGF.Builder .CreateElementBitCast (addr, ScalarType);
1164
- IGF.Builder .CreateStore (explosion.claimNext (), addr);
1173
+ auto index = ScalarTypes.size ();
1174
+ for (auto scalarTy : ScalarTypes) {
1175
+ addr = IGF.Builder .CreateElementBitCast (addr, scalarTy);
1176
+ IGF.Builder .CreateStore (explosion.claimNext (), addr);
1177
+ --index;
1178
+ // Advance to next scalar chunk.
1179
+ if (index > 0 ) {
1180
+ addr = IGF.Builder .CreateElementBitCast (addr, IGF.IGM .Int8Ty );
1181
+ auto currentScalarTypeSize = Size (scalarTy->getIntegerBitWidth ()/8 );
1182
+ addr = IGF.Builder .CreateConstByteArrayGEP (addr, currentScalarTypeSize);
1183
+ }
1184
+ }
1165
1185
}
1166
1186
1167
1187
void reexplode (IRGenFunction &IGF, Explosion &sourceExplosion,
1168
1188
Explosion &targetExplosion) const override {
1169
- targetExplosion.add (sourceExplosion.claimNext ());
1189
+ for (auto scalarTy : ScalarTypes) {
1190
+ (void )scalarTy;
1191
+ targetExplosion.add (sourceExplosion.claimNext ());
1192
+ }
1170
1193
}
1171
1194
1172
1195
void copy (IRGenFunction &IGF, Explosion &sourceExplosion,
@@ -1176,11 +1199,11 @@ namespace {
1176
1199
1177
1200
void consume (IRGenFunction &IGF, Explosion &explosion,
1178
1201
Atomicity atomicity) const override {
1179
- explosion.claimNext ();
1202
+ ( void ) explosion.claimAll ();
1180
1203
}
1181
1204
1182
1205
void fixLifetime (IRGenFunction &IGF, Explosion &explosion) const override {
1183
- explosion.claimNext ();
1206
+ ( void ) explosion.claimAll ();
1184
1207
}
1185
1208
1186
1209
void destroy (IRGenFunction &IGF, Address address, SILType T,
@@ -1189,7 +1212,9 @@ namespace {
1189
1212
}
1190
1213
1191
1214
void getSchema (ExplosionSchema &schema) const override {
1192
- schema.add (ExplosionSchema::Element::forScalar (ScalarType));
1215
+ for (auto scalarTy: ScalarTypes) {
1216
+ schema.add (ExplosionSchema::Element::forScalar (scalarTy));
1217
+ }
1193
1218
}
1194
1219
1195
1220
void addToAggLowering (IRGenModule &IGM, SwiftAggLowering &lowering,
@@ -1202,14 +1227,20 @@ namespace {
1202
1227
EnumPayload &payload,
1203
1228
Explosion &source,
1204
1229
unsigned offset) const override {
1205
- payload.insertValue (IGF, source.claimNext (), offset);
1230
+ for (auto scalarTy: ScalarTypes) {
1231
+ payload.insertValue (IGF, source.claimNext (), offset);
1232
+ offset += scalarTy->getIntegerBitWidth ();
1233
+ }
1206
1234
}
1207
1235
1208
1236
void unpackFromEnumPayload (IRGenFunction &IGF,
1209
1237
const EnumPayload &payload,
1210
1238
Explosion &target,
1211
1239
unsigned offset) const override {
1212
- target.add (payload.extractValue (IGF, ScalarType, offset));
1240
+ for (auto scalarTy : ScalarTypes) {
1241
+ target.add (payload.extractValue (IGF, scalarTy, offset));
1242
+ offset += scalarTy->getIntegerBitWidth ();
1243
+ }
1213
1244
}
1214
1245
};
1215
1246
@@ -1946,10 +1977,28 @@ TypeConverter::getOpaqueStorageTypeInfo(Size size, Alignment align) {
1946
1977
// Use an [N x i8] array for storage, but load and store as a single iNNN
1947
1978
// scalar.
1948
1979
auto storageType = llvm::ArrayType::get (IGM.Int8Ty , size.getValue ());
1949
- auto intType = llvm::IntegerType::get (IGM.getLLVMContext (),
1950
- size.getValueInBits ());
1980
+
1981
+ // Create chunks of MAX_INT_BITS integer scalar types if neccessary.
1982
+ std::vector<llvm::IntegerType*> scalarTypes;
1983
+ Size chunkSize = size;
1984
+ auto maxChunkSize = Size (llvm::IntegerType::MAX_INT_BITS/8 );
1985
+ while (chunkSize) {
1986
+ if (chunkSize > maxChunkSize) {
1987
+ auto intType = llvm::IntegerType::get (IGM.getLLVMContext (),
1988
+ maxChunkSize.getValueInBits ());
1989
+ scalarTypes.push_back (intType);
1990
+ chunkSize -= maxChunkSize;
1991
+ continue ;
1992
+ }
1993
+ auto intType = llvm::IntegerType::get (IGM.getLLVMContext (),
1994
+ chunkSize.getValueInBits ());
1995
+ scalarTypes.push_back (intType);
1996
+ chunkSize = Size (0 );
1997
+ }
1998
+
1951
1999
// There are no spare bits in an opaque storage type.
1952
- auto type = new OpaqueStorageTypeInfo (storageType, intType, size,
2000
+ auto type = new OpaqueStorageTypeInfo (storageType, std::move (scalarTypes),
2001
+ size,
1953
2002
SpareBitVector::getConstant (size.getValueInBits (), false ),
1954
2003
align);
1955
2004
0 commit comments