KeyPaths: Take a bit for encoding "let"-ness of stored properties.

If we know a key path component can be accessed as a stored property, then we should also know whether it's a `let` or not, so it should be safe to encode this in the key path pattern. Stage this change in by changing the number of bits used to store in-line offsets, fixing up the parts of the key path implementation that assumed that it took up the entire payload bitfield.
This commit is contained in:
Joe Groff
2018-08-16 13:17:28 -07:00
parent c11aacc576
commit 00b50ce6ab
7 changed files with 73 additions and 47 deletions

View File

@@ -773,22 +773,23 @@ emitKeyPathComponent(IRGenModule &IGM,
case KeyPathPatternComponent::Kind::StoredProperty: {
auto property = cast<VarDecl>(component.getStoredPropertyDecl());
auto addFixedOffset = [&](bool isStruct, llvm::Constant *offset) {
auto addFixedOffset = [&](bool isStruct, bool isLet,
llvm::Constant *offset) {
if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
auto offsetValue = offsetInt->getValue().getZExtValue();
if (KeyPathComponentHeader::offsetCanBeInline(offsetValue)) {
auto header = isStruct
? KeyPathComponentHeader
::forStructComponentWithInlineOffset(offsetValue)
::forStructComponentWithInlineOffset(isLet, offsetValue)
: KeyPathComponentHeader
::forClassComponentWithInlineOffset(offsetValue);
::forClassComponentWithInlineOffset(isLet, offsetValue);
fields.addInt32(header.getData());
return;
}
}
auto header = isStruct
? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset()
: KeyPathComponentHeader::forClassComponentWithOutOfLineOffset();
? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset(isLet)
: KeyPathComponentHeader::forClassComponentWithOutOfLineOffset(isLet);
fields.addInt32(header.getData());
fields.add(llvm::ConstantExpr::getTruncOrBitCast(offset, IGM.Int32Ty));
};
@@ -801,7 +802,7 @@ emitKeyPathComponent(IRGenModule &IGM,
loweredBaseTy,
property)) {
// We have a known constant fixed offset.
addFixedOffset(/*struct*/ true, offset);
addFixedOffset(/*struct*/ true, property->isLet(), offset);
break;
}
@@ -811,7 +812,7 @@ emitKeyPathComponent(IRGenModule &IGM,
auto fieldOffset = metadataLayout.getStaticFieldOffset(property);
auto header = KeyPathComponentHeader
::forStructComponentWithUnresolvedFieldOffset();
::forStructComponentWithUnresolvedFieldOffset(property->isLet());
fields.addInt32(header.getData());
fields.addInt32(fieldOffset.getValue());
break;
@@ -829,14 +830,14 @@ emitKeyPathComponent(IRGenModule &IGM,
loweredBaseTy,
property);
assert(offset && "no constant offset for ConstantDirect field?!");
addFixedOffset(/*struct*/ false, offset);
addFixedOffset(/*struct*/ false, property->isLet(), offset);
break;
}
case FieldAccess::NonConstantDirect: {
// A constant offset that's determined at class realization time.
// We have to load the offset from a global ivar.
auto header = KeyPathComponentHeader
::forClassComponentWithUnresolvedIndirectOffset();
::forClassComponentWithUnresolvedIndirectOffset(property->isLet());
fields.addInt32(header.getData());
fields.addAlignmentPadding(IGM.getPointerAlignment());
auto offsetVar = IGM.getAddrOfFieldOffset(property, NotForDefinition);
@@ -846,8 +847,8 @@ emitKeyPathComponent(IRGenModule &IGM,
case FieldAccess::ConstantIndirect: {
// An offset that depends on the instance's generic parameterization,
// but whose field offset is at a known vtable offset.
auto header =
KeyPathComponentHeader::forClassComponentWithUnresolvedFieldOffset();
auto header = KeyPathComponentHeader
::forClassComponentWithUnresolvedFieldOffset(property->isLet());
fields.addInt32(header.getData());
auto fieldOffset =
getClassFieldOffsetOffset(IGM,