mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Use the first element of a struct as a source for
extra inhabitants. Obviously this should eventually be generalized to take from any element, but this is good enough to give us zero-cost abstraction via single-field structs. Contains some bugfixes for the tuple-extra-inhabitant changes as well, because test coverage for optional structs is obviously quite a bit richer than for optional tuples. All of this is leading towards unblocking IRGen for importing CFStringRef as Unmanaged<CFString>!. Swift SVN r17243
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