@@ -198,67 +198,37 @@ void EnumPayload::insertValue(IRGenFunction &IGF, llvm::Value *value,
198
198
199
199
llvm::Value *EnumPayload::extractValue (IRGenFunction &IGF, llvm::Type *type,
200
200
unsigned payloadOffset) const {
201
- llvm::Value *result = nullptr ;
202
- withValueInPayload (IGF, *this , type, -1 , payloadOffset,
203
- [&](LazyValue &payloadValue,
204
- unsigned payloadBitWidth,
205
- unsigned payloadValueOffset,
206
- unsigned valueBitWidth,
207
- unsigned valueOffset) {
208
- auto payloadType = getPayloadType (payloadValue);
209
- // If the desired type matches the payload slot exactly, we don't need
210
- // to do anything.
211
- if (payloadValueOffset == 0 && valueOffset == 0 ) {
212
- if (type == payloadType) {
213
- result = forcePayloadValue (payloadValue);
214
- return ;
215
- }
216
- // If only the width matches exactly, do a bitcast.
217
- if (payloadBitWidth == valueBitWidth) {
218
- result =
219
- IGF.Builder .CreateBitOrPointerCast (forcePayloadValue (payloadValue),
220
- type);
221
- return ;
222
- }
223
- }
224
-
225
- // Integrate the chunk of payload into the result value.
226
- auto value = forcePayloadValue (payloadValue);
227
- auto valueIntTy =
228
- llvm::IntegerType::get (IGF.IGM .getLLVMContext (), valueBitWidth);
229
- auto payloadIntTy =
230
- llvm::IntegerType::get (IGF.IGM .getLLVMContext (), payloadBitWidth);
231
-
232
- value = IGF.Builder .CreateBitOrPointerCast (value, payloadIntTy);
233
- if (IGF.IGM .Triple .isLittleEndian ()) {
234
- if (payloadValueOffset > 0 )
235
- value = IGF.Builder .CreateLShr (value,
236
- llvm::ConstantInt::get (value->getType (), payloadValueOffset));
237
- } else {
238
- if ((valueBitWidth == 32 || valueBitWidth == 16 || valueBitWidth == 8 || valueBitWidth == 1 ) &&
239
- payloadBitWidth > (payloadValueOffset + valueBitWidth)) {
240
- unsigned shiftBitWidth = valueBitWidth;
241
- if (valueBitWidth == 1 ) {
242
- shiftBitWidth = 8 ;
243
- }
244
- value = IGF.Builder .CreateLShr (value,
245
- llvm::ConstantInt::get (value->getType (), (payloadBitWidth - shiftBitWidth) - payloadValueOffset));
246
- }
247
- }
248
- if (valueBitWidth > payloadBitWidth)
249
- value = IGF.Builder .CreateZExt (value, valueIntTy);
250
- if (valueOffset > 0 )
251
- value = IGF.Builder .CreateShl (value,
252
- llvm::ConstantInt::get (value->getType (), valueOffset));
253
- if (valueBitWidth < payloadBitWidth)
254
- value = IGF.Builder .CreateTrunc (value, valueIntTy);
255
-
256
- if (!result)
257
- result = value;
258
- else
259
- result = IGF.Builder .CreateOr (result, value);
260
- });
261
- return IGF.Builder .CreateBitOrPointerCast (result, type);
201
+ auto &DL = IGF.IGM .DataLayout ;
202
+ auto &C = IGF.IGM .getLLVMContext ();
203
+
204
+ // Create a mask for the bytes that make up the stored value by
205
+ // by zero extending the value mask to its storage size.
206
+ // This makes the mask valid regardless of endianness.
207
+ auto valueSize = DL.getTypeSizeInBits (type);
208
+ auto valueMask = APInt::getLowBitsSet (DL.getTypeStoreSizeInBits (type),
209
+ valueSize);
210
+
211
+ // Pad the valueMask so that it can be applied to the entire
212
+ // payload.
213
+ auto payloadMask = APInt::getNullValue (getAllocSizeInBits (DL));
214
+ payloadMask.insertBits (valueMask, payloadOffset);
215
+
216
+ // Convert the payload mask into a SpareBitVector.
217
+ // TODO: make emitGatherSpareBits take an APInt and delete.
218
+ auto mask = SpareBitVector::fromAPInt (std::move (payloadMask));
219
+
220
+ // Gather the value from the payload.
221
+ auto value = emitGatherSpareBits (IGF, mask, 0 , valueSize);
222
+
223
+ // Convert the integer value to the required type.
224
+ if (DL.getTypeSizeInBits (value->getType ()) > valueSize) {
225
+ auto intTy = llvm::IntegerType::get (C, valueSize);
226
+ value = IGF.Builder .CreateTrunc (value, intTy);
227
+ }
228
+ if (value->getType () != type) {
229
+ value = IGF.Builder .CreateBitOrPointerCast (value, type);
230
+ }
231
+ return value;
262
232
}
263
233
264
234
EnumPayload EnumPayload::fromExplosion (IRGenModule &IGM,
@@ -625,3 +595,12 @@ EnumPayload::emitGatherSpareBits(IRGenFunction &IGF,
625
595
return llvm::ConstantInt::get (destTy, 0 );
626
596
return spareBitValue;
627
597
}
598
+
599
+ unsigned EnumPayload::getAllocSizeInBits (const llvm::DataLayout &DL) const {
600
+ unsigned size = 0u ;
601
+ for (const auto &pv : PayloadValues) {
602
+ size += DL.getTypeAllocSizeInBits (getPayloadType (pv));
603
+ assert (size % 8 == 0 && " allocation size must be a multiple of bytes" );
604
+ }
605
+ return size;
606
+ }
0 commit comments