mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Use the first element of structs and tuples as a source
for extra inhabitants. For structs in particular, this eliminates a major source of abstraction penatlies. For example, an optional struct containing an object pointer is now represented the same way as an optional object pointer, which is critical for correctly importing CF types as Unmanaged<T>!. In time, we should generalize this to consider all elements as sources for extra inhabitants, as well as exploiting spare bits in the representation, but getting the single-element case right really provides the bulk of the benefit. This commit restores r17242 and r17243 with a fix to use value witnesses that actually forward the right type metadata down. We were already generating these value witnesses in the dependent struct VWT pattern, but I was being too clever and trying to use the underlying value witness directly. Swift SVN r17267
This commit is contained in:
@@ -123,6 +123,62 @@ namespace {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// For now, just use extra inhabitants from the first field.
|
||||
// FIXME: generalize
|
||||
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
|
||||
if (asImpl().getFields().empty()) return false;
|
||||
return asImpl().getFields()[0].getTypeInfo().mayHaveExtraInhabitants(IGM);
|
||||
}
|
||||
|
||||
// This is dead code in NonFixedStructTypeInfo.
|
||||
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const {
|
||||
if (asImpl().getFields().empty()) return 0;
|
||||
auto &fieldTI = cast<FixedTypeInfo>(asImpl().getFields()[0].getTypeInfo());
|
||||
return fieldTI.getFixedExtraInhabitantCount(IGM);
|
||||
}
|
||||
|
||||
// This is dead code in NonFixedStructTypeInfo.
|
||||
llvm::ConstantInt *getFixedExtraInhabitantValue(IRGenModule &IGM,
|
||||
unsigned bits,
|
||||
unsigned index) const {
|
||||
auto &fieldTI = cast<FixedTypeInfo>(asImpl().getFields()[0].getTypeInfo());
|
||||
return fieldTI.getFixedExtraInhabitantValue(IGM, bits, index);
|
||||
}
|
||||
|
||||
// This is dead code in NonFixedStructTypeInfo.
|
||||
llvm::Value *maskFixedExtraInhabitant(IRGenFunction &IGF,
|
||||
llvm::Value *structValue) const {
|
||||
// Truncate down to the width of the field, mask it recursively,
|
||||
// and then zext back out to the payload size.
|
||||
auto &fieldTI = cast<FixedTypeInfo>(asImpl().getFields()[0].getTypeInfo());
|
||||
unsigned fieldWidth = fieldTI.getFixedSize().getValueInBits();
|
||||
auto fieldTy = llvm::IntegerType::get(IGF.IGM.getLLVMContext(), fieldWidth);
|
||||
auto fieldValue = IGF.Builder.CreateTrunc(structValue, fieldTy);
|
||||
fieldValue = fieldTI.maskFixedExtraInhabitant(IGF, fieldValue);
|
||||
return IGF.Builder.CreateZExt(fieldValue, structValue->getType());
|
||||
}
|
||||
|
||||
llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
|
||||
Address structAddr,
|
||||
CanType structType) const override {
|
||||
auto &field = asImpl().getFields()[0];
|
||||
Address fieldAddr =
|
||||
asImpl().projectFieldAddress(IGF, structAddr, structType, field.Field);
|
||||
return field.getTypeInfo().getExtraInhabitantIndex(IGF, fieldAddr,
|
||||
field.getType(IGF.IGM, structType));
|
||||
}
|
||||
|
||||
void storeExtraInhabitant(IRGenFunction &IGF,
|
||||
llvm::Value *index,
|
||||
Address structAddr,
|
||||
CanType structType) const override {
|
||||
auto &field = asImpl().getFields()[0];
|
||||
Address fieldAddr =
|
||||
asImpl().projectFieldAddress(IGF, structAddr, structType, field.Field);
|
||||
field.getTypeInfo().storeExtraInhabitant(IGF, index, fieldAddr,
|
||||
field.getType(IGF.IGM, structType));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -149,14 +205,6 @@ namespace {
|
||||
Nothing_t getNonFixedOffsets(IRGenFunction &IGF) const {
|
||||
return Nothing;
|
||||
}
|
||||
|
||||
// FIXME: Suppress use of extra inhabitants for single-payload enum layout
|
||||
// until we're ready to handle the runtime logic for exporting extra
|
||||
// inhabitants through generic structs.
|
||||
bool mayHaveExtraInhabitants(IRGenModule&) const override { return false; }
|
||||
unsigned getFixedExtraInhabitantCount(IRGenModule&) const override {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// A type implementation for non-loadable but fixed-size struct types.
|
||||
@@ -176,14 +224,6 @@ namespace {
|
||||
return Nothing;
|
||||
}
|
||||
Nothing_t getNonFixedOffsets(IRGenFunction &IGF) const { return Nothing; }
|
||||
|
||||
// FIXME: Suppress use of extra inhabitants for single-payload enum layout
|
||||
// until we're ready to handle the runtime logic for exporting extra
|
||||
// inhabitants through generic structs.
|
||||
bool mayHaveExtraInhabitants(IRGenModule&) const override { return false; }
|
||||
unsigned getFixedExtraInhabitantCount(IRGenModule&) const override {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/// Find the beginning of the field offset vector in a struct's metadata.
|
||||
|
||||
Reference in New Issue
Block a user