Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime support for identity key paths. #18804

Merged
merged 2 commits into from
Aug 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,11 @@ BUILTIN_SIL_OPERATION(AllocWithTailElems, "allocWithTailElems", Special)
/// Projects the first tail-allocated element of type E from a class C.
BUILTIN_SIL_OPERATION(ProjectTailElems, "projectTailElems", Special)

/// identityKeyPath : <T> () -> WritableKeyPath<T, T>
///
/// Creates an identity key path object. (TODO: replace with proper syntax)
BUILTIN_SIL_OPERATION(IdentityKeyPath, "identityKeyPath", Special)

#undef BUILTIN_SIL_OPERATION

// BUILTIN_RUNTIME_CALL - A call into a runtime function.
Expand Down
2 changes: 0 additions & 2 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,6 @@ ERROR(sil_keypath_computed_property_missing_part,none,
ERROR(sil_keypath_external_missing_part,none,
"keypath external component with indices needs an indices_equals and "
"indices_hash function", ())
ERROR(sil_keypath_no_components,none,
"keypath must have at least one component", ())
ERROR(sil_keypath_no_root,none,
"keypath must have a root component declared",())
ERROR(sil_keypath_index_not_hashable,none,
Expand Down
26 changes: 26 additions & 0 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,20 @@ makeTuple(const Gs & ...elementGenerators) {
};
}

template <class... Gs>
static BuiltinGenericSignatureBuilder::LambdaGenerator
makeBoundGenericType(NominalTypeDecl *decl,
const Gs & ...argumentGenerators) {
return {
[=](BuiltinGenericSignatureBuilder &builder) -> Type {
Type args[] = {
argumentGenerators.build(builder)...
};
return BoundGenericType::get(decl, Type(), args);
}
};
}

template <class T>
static BuiltinGenericSignatureBuilder::MetatypeGenerator<T>
makeMetatype(const T &object, Optional<MetatypeRepresentation> repr = None) {
Expand Down Expand Up @@ -972,6 +986,15 @@ static ValueDecl *getTypeJoinMetaOperation(ASTContext &Context, Identifier Id) {
return builder.build(Id);
}

static ValueDecl *getIdentityKeyPathOperation(ASTContext &Context,
Identifier Id) {
BuiltinGenericSignatureBuilder builder(Context, 1);
auto arg = makeGenericParam();
builder.setResult(makeBoundGenericType(Context.getWritableKeyPathDecl(),
arg, arg));
return builder.build(Id);
}

static ValueDecl *getCanBeObjCClassOperation(ASTContext &Context,
Identifier Id) {
// <T> T.Type -> Builtin.Int8
Expand Down Expand Up @@ -1865,6 +1888,9 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {

case BuiltinValueKind::TypeJoinMeta:
return getTypeJoinMetaOperation(Context, Id);

case BuiltinValueKind::IdentityKeyPath:
return getIdentityKeyPathOperation(Context, Id);
}

llvm_unreachable("bad builtin value!");
Expand Down
9 changes: 6 additions & 3 deletions lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2884,8 +2884,6 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
return true;
}

if (components.empty())
P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_components);
if (rootType.isNull())
P.diagnose(InstLoc.getSourceLoc(), diag::sil_keypath_no_root);

Expand Down Expand Up @@ -2943,8 +2941,13 @@ bool SILParser::parseSILInstruction(SILBuilder &B) {
if (patternEnv && patternEnv->getGenericSignature()) {
canSig = patternEnv->getGenericSignature()->getCanonicalSignature();
}
CanType leafType;
if (!components.empty())
leafType = components.back().getComponentType();
else
leafType = rootType;
auto pattern = KeyPathPattern::get(B.getModule(), canSig,
rootType, components.back().getComponentType(),
rootType, leafType,
components, objcString);

ResultVal = B.createKeyPath(InstLoc, pattern, subMap, operands, Ty);
Expand Down
48 changes: 3 additions & 45 deletions lib/SIL/SILOwnershipVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,56 +1288,14 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Swift3ImplicitObjCEntrypoint)

// Builtins that should be lowered to SIL instructions so we should never see
// them.
#define BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ID) \
#define BUILTIN_SIL_OPERATION(ID, NAME, CATEGORY) \
OwnershipUseCheckerResult \
OwnershipCompatibilityBuiltinUseChecker::visit##ID(BuiltinInst *BI, \
StringRef Attr) { \
llvm_unreachable("Builtin should have been lowered to SIL instruction?!"); \
}
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Retain)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Release)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Autorelease)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(TryPin)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Unpin)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Load)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadRaw)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(LoadInvariant)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Take)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Destroy)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Assign)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Init)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastToNativeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(UnsafeCastToNativeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastFromNativeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastToBridgeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(
CastReferenceFromBridgeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(
CastBitPatternFromBridgeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ClassifyBridgeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ValueToBridgeObject)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BridgeToRawPointer)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BridgeFromRawPointer)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CastReference)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ReinterpretCast)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AddressOf)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AddressOfBorrow)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GepRaw)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(Gep)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(GetTailAddr)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(PerformInstantaneousReadAccess)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BeginUnpairedModifyAccess)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(EndUnpairedAccess)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(CondFail)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(FixLifetime)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUnique)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUniqueOrPinned)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUnique_native)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(IsUniqueOrPinned_native)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(BindMemory)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(AllocWithTailElems)
BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS(ProjectTailElems)
#undef BUILTINS_THAT_SHOULD_HAVE_BEEN_LOWERED_TO_SILINSTS
#define BUILTIN(X, Y, Z)
#include "swift/AST/Builtins.def"

OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitBuiltinInst(BuiltinInst *BI) {
Expand Down
50 changes: 9 additions & 41 deletions lib/SIL/ValueOwnershipKindClassifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,8 +397,6 @@ struct ValueOwnershipKindBuiltinVisitor
} \
return ValueOwnershipKind::OWNERSHIP; \
}
CONSTANT_OWNERSHIP_BUILTIN(Owned, Take)
CONSTANT_OWNERSHIP_BUILTIN(Owned, TryPin)
// This returns a value at +1 that is destroyed strictly /after/ the
// UnsafeGuaranteedEnd. This provides the guarantee that we want.
CONSTANT_OWNERSHIP_BUILTIN(Owned, UnsafeGuaranteed)
Expand Down Expand Up @@ -443,9 +441,6 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, ICMP_ULE)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ICMP_ULT)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IntToPtr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LShr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Load)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadRaw)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, LoadInvariant)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Mul)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Or)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, PtrToInt)
Expand All @@ -472,32 +467,7 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, ZExt)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ZExtOrBitCast)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FCMP_ORD)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FCMP_UNO)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastToNativeObject)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, UnsafeCastToNativeObject)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastFromNativeObject)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastToBridgeObject)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastReferenceFromBridgeObject)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, CastBitPatternFromBridgeObject)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ClassifyBridgeObject)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BridgeToRawPointer)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, BridgeFromRawPointer)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, CastReference)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AddressOf)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AddressOfBorrow)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GepRaw)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Gep)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, GetTailAddr)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, PerformInstantaneousReadAccess)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BeginUnpairedModifyAccess)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, EndUnpairedAccess)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, OnFastPath)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUnique)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUniqueOrPinned)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUnique_native)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsUniqueOrPinned_native)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, BindMemory)
CONSTANT_OWNERSHIP_BUILTIN(Owned, AllocWithTailElems)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ProjectTailElems)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, IsOptionalType)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Sizeof)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Strideof)
Expand Down Expand Up @@ -543,21 +513,11 @@ CONSTANT_OWNERSHIP_BUILTIN(Trivial, UnexpectedError)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, ErrorInMain)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, DeallocRaw)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Fence)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Retain)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Release)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, CondFail)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, FixLifetime)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Autorelease)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Unpin)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Destroy)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Assign)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Init)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, AtomicStore)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Once)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, OnceWithContext)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, TSanInoutAccess)
CONSTANT_OWNERSHIP_BUILTIN(Trivial, Swift3ImplicitObjCEntrypoint)
CONSTANT_OWNERSHIP_BUILTIN(Unowned, ValueToBridgeObject)

#undef CONSTANT_OWNERSHIP_BUILTIN

Expand All @@ -570,14 +530,22 @@ CONSTANT_OWNERSHIP_BUILTIN(Unowned, ValueToBridgeObject)
} \
return ValueOwnershipKind::Unowned; \
}
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ReinterpretCast)
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(CmpXChg)
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(AtomicLoad)
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ExtractElement)
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(InsertElement)
UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT(ZeroInitializer)
#undef UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT

#define BUILTIN(X,Y,Z)
#define BUILTIN_SIL_OPERATION(ID, NAME, CATEGORY) \
ValueOwnershipKind ValueOwnershipKindBuiltinVisitor::visit##ID( \
BuiltinInst *BI, StringRef Attr) { \
llvm_unreachable("builtin should have been lowered in SILGen"); \
}

#include "swift/AST/Builtins.def"

ValueOwnershipKind
ValueOwnershipKindClassifier::visitBuiltinInst(BuiltinInst *BI) {
// For now, just conservatively say builtins are None. We need to use a
Expand Down
53 changes: 53 additions & 0 deletions lib/SILGen/SILGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Builtins.h"
#include "swift/AST/DiagnosticsSIL.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
#include "swift/AST/ReferenceCounting.h"
#include "swift/SIL/SILArgument.h"
Expand Down Expand Up @@ -1055,6 +1056,58 @@ static ManagedValue emitBuiltinProjectTailElems(SILGenFunction &SGF,
return ManagedValue::forUnmanaged(result);
}

static ManagedValue emitBuiltinIdentityKeyPath(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {
assert(subs.getReplacementTypes().size() == 1 &&
"identityKeyPath should have one substitution");
assert(args.size() == 0 &&
"identityKeyPath should have no args");

auto identityTy = subs.getReplacementTypes()[0]->getCanonicalType();

// The `self` key can be used for identity in Cocoa KVC as well.
StringRef objcString = SGF.getASTContext().LangOpts.EnableObjCInterop
? "self" : "";

// The key path pattern has to capture some generic context if the type is
// dependent on this generic context. We only need the specific type, though,
// not the entire generic environment.
bool isDependent = identityTy->hasArchetype();
CanType identityPatternTy = identityTy;
CanGenericSignature patternSig = nullptr;
SubstitutionMap patternSubs;
if (isDependent) {
auto param = GenericTypeParamType::get(0, 0, SGF.getASTContext());
identityPatternTy = param->getCanonicalType();
patternSig = GenericSignature::get(param, {})->getCanonicalSignature();
patternSubs = SubstitutionMap::get(patternSig,
llvm::makeArrayRef((Type)identityTy),
{});
}

auto identityPattern = KeyPathPattern::get(SGF.SGM.M,
patternSig,
identityPatternTy,
identityPatternTy,
{},
objcString);

auto kpTy = BoundGenericType::get(SGF.getASTContext().getWritableKeyPathDecl(),
Type(),
{identityTy, identityTy})
->getCanonicalType();

auto keyPath = SGF.B.createKeyPath(loc, identityPattern,
patternSubs,
{},
SILType::getPrimitiveObjectType(kpTy));
return SGF.emitManagedRValueWithCleanup(keyPath);
}


/// Specialized emitter for type traits.
template<TypeTraitResult (TypeBase::*Trait)(),
BuiltinValueKind Kind>
Expand Down
Loading