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:
John McCall
2014-05-02 10:29:55 +00:00
parent 422df2e3bb
commit c0e4242bec
8 changed files with 142 additions and 50 deletions

View File

@@ -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.