@@ -1117,16 +1117,16 @@ namespace {
11171117 class OpaqueStorageTypeInfo final :
11181118 public ScalarTypeInfo<OpaqueStorageTypeInfo, LoadableTypeInfo>
11191119 {
1120- llvm::IntegerType *ScalarType ;
1120+ std::vector< llvm::IntegerType *> ScalarTypes ;
11211121 public:
11221122 OpaqueStorageTypeInfo (llvm::ArrayType *storage,
1123- llvm::IntegerType *scalarType ,
1123+ std::vector< llvm::IntegerType *> &&scalarTypes ,
11241124 Size size,
11251125 SpareBitVector &&spareBits,
11261126 Alignment align)
11271127 : ScalarTypeInfo(storage, size, std::move(spareBits), align, IsPOD,
11281128 IsFixedSize),
1129- ScalarType (scalarType )
1129+ ScalarTypes (std::move(scalarTypes) )
11301130 {}
11311131
11321132 llvm::ArrayType *getStorageType () const {
@@ -1139,7 +1139,7 @@ namespace {
11391139 }
11401140
11411141 unsigned getExplosionSize () const override {
1142- return 1 ;
1142+ return ScalarTypes. size () ;
11431143 }
11441144
11451145 void loadAsCopy (IRGenFunction &IGF, Address addr,
@@ -1149,8 +1149,18 @@ namespace {
11491149
11501150 void loadAsTake (IRGenFunction &IGF, Address addr,
11511151 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+ }
11541164 }
11551165
11561166 void assign (IRGenFunction &IGF, Explosion &explosion, Address addr,
@@ -1160,13 +1170,26 @@ namespace {
11601170
11611171 void initialize (IRGenFunction &IGF, Explosion &explosion, Address addr,
11621172 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+ }
11651185 }
11661186
11671187 void reexplode (IRGenFunction &IGF, Explosion &sourceExplosion,
11681188 Explosion &targetExplosion) const override {
1169- targetExplosion.add (sourceExplosion.claimNext ());
1189+ for (auto scalarTy : ScalarTypes) {
1190+ (void )scalarTy;
1191+ targetExplosion.add (sourceExplosion.claimNext ());
1192+ }
11701193 }
11711194
11721195 void copy (IRGenFunction &IGF, Explosion &sourceExplosion,
@@ -1176,11 +1199,11 @@ namespace {
11761199
11771200 void consume (IRGenFunction &IGF, Explosion &explosion,
11781201 Atomicity atomicity) const override {
1179- explosion.claimNext ();
1202+ ( void ) explosion.claimAll ();
11801203 }
11811204
11821205 void fixLifetime (IRGenFunction &IGF, Explosion &explosion) const override {
1183- explosion.claimNext ();
1206+ ( void ) explosion.claimAll ();
11841207 }
11851208
11861209 void destroy (IRGenFunction &IGF, Address address, SILType T,
@@ -1189,7 +1212,9 @@ namespace {
11891212 }
11901213
11911214 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+ }
11931218 }
11941219
11951220 void addToAggLowering (IRGenModule &IGM, SwiftAggLowering &lowering,
@@ -1202,14 +1227,20 @@ namespace {
12021227 EnumPayload &payload,
12031228 Explosion &source,
12041229 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+ }
12061234 }
12071235
12081236 void unpackFromEnumPayload (IRGenFunction &IGF,
12091237 const EnumPayload &payload,
12101238 Explosion &target,
12111239 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+ }
12131244 }
12141245 };
12151246
@@ -1946,10 +1977,28 @@ TypeConverter::getOpaqueStorageTypeInfo(Size size, Alignment align) {
19461977 // Use an [N x i8] array for storage, but load and store as a single iNNN
19471978 // scalar.
19481979 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+
19511999 // 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,
19532002 SpareBitVector::getConstant (size.getValueInBits (), false ),
19542003 align);
19552004
0 commit comments