Skip to content

Staging flag for partial_apply simplification #5213

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

Merged
merged 2 commits into from
Oct 10, 2016
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/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3268,6 +3268,11 @@ class ClassDecl : public NominalTypeDecl {
bool usesObjCGenericsModel() const {
return isObjC() && hasClangNode() && isGenericContext();
}

/// True if the class is known to be implemented in Swift.
bool hasKnownSwiftImplementation() const {
return !hasClangNode();
}
};


Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/SILOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class SILOptions {
/// conventions.
bool EnableGuaranteedClosureContexts = false;

/// Don't generate code using partial_apply in SIL generation.
bool DisableSILPartialApply = false;

/// The name of the SIL outputfile if compiled with SIL debugging (-gsil).
std::string SILOutputFileNameForDebugging;
};
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,9 @@ def disable_arc_opts : Flag<["-"], "disable-arc-opts">,
def enable_guaranteed_closure_contexts : Flag<["-"], "enable-guaranteed-closure-contexts">,
HelpText<"Use @guaranteed convention for closure context">;

def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
HelpText<"Disable use of partial_apply in SIL generation">;

def remove_runtime_asserts : Flag<["-"], "remove-runtime-asserts">,
HelpText<"Remove runtime asserts.">;

Expand Down
2 changes: 2 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
Opts.EmitProfileCoverageMapping |= Args.hasArg(OPT_profile_coverage_mapping);
Opts.EnableGuaranteedClosureContexts |=
Args.hasArg(OPT_enable_guaranteed_closure_contexts);
Opts.DisableSILPartialApply |=
Args.hasArg(OPT_disable_sil_partial_apply);

if (Args.hasArg(OPT_debug_on_sil)) {
// Derive the name of the SIL file for debugging from
Expand Down
2 changes: 1 addition & 1 deletion lib/IRGen/GenCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,

// If the destination type is known to have a Swift-compatible
// implementation, use the most specific entrypoint.
if (destClass && hasKnownSwiftImplementation(IGF.IGM, destClass)) {
if (destClass && destClass->hasKnownSwiftImplementation()) {
metadataRef = IGF.emitTypeMetadataRef(toType.getSwiftRValueType());

switch (mode) {
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/GenClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ ReferenceCounting irgen::getReferenceCountingForClass(IRGenModule &IGM,
// NOTE: if you change this, change Type::usesNativeReferenceCounting.
// If the root class is implemented in swift, then we have a swift
// refcount; otherwise, we have an ObjC refcount.
if (hasKnownSwiftImplementation(IGM, getRootClass(theClass)))
if (getRootClass(theClass)->hasKnownSwiftImplementation())
return ReferenceCounting::Native;

return ReferenceCounting::ObjC;
Expand All @@ -83,7 +83,7 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
CanType type) {
if (auto theClass = type->getClassOrBoundGenericClass()) {
// We can access the isas of pure Swift classes directly.
if (hasKnownSwiftImplementation(IGM, getRootClass(theClass)))
if (getRootClass(theClass)->hasKnownSwiftImplementation())
return IsaEncoding::Pointer;
// For ObjC or mixed classes, we need to use object_getClass.
return IsaEncoding::ObjC;
Expand Down
9 changes: 2 additions & 7 deletions lib/IRGen/GenMeta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,12 +435,7 @@ bool irgen::hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass) {
// is enough to conclusively force us into a slower path.
// Eventually we might have an attribute here or something based on
// the deployment target.
return hasKnownSwiftImplementation(IGM, theClass);
}

/// Is the given class known to have an implementation in Swift?
bool irgen::hasKnownSwiftImplementation(IRGenModule &IGM, ClassDecl *theClass) {
return !theClass->hasClangNode();
return theClass->hasKnownSwiftImplementation();
}

/// Is the given method known to be callable by vtable lookup?
Expand All @@ -451,7 +446,7 @@ bool irgen::hasKnownVTableEntry(IRGenModule &IGM,
if (!theClass) {
return false;
}
return hasKnownSwiftImplementation(IGM, theClass);
return theClass->hasKnownSwiftImplementation();
}

/// Is it basically trivial to access the given metadata? If so, we don't
Expand Down
3 changes: 0 additions & 3 deletions lib/IRGen/GenMeta.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ namespace irgen {
/// metadata?
bool hasKnownSwiftMetadata(IRGenModule &IGM, CanType theType);

/// Is the given class known to have an implementation in Swift?
bool hasKnownSwiftImplementation(IRGenModule &IGM, ClassDecl *theClass);

/// Is the given method known to be callable by vtable dispatch?
bool hasKnownVTableEntry(IRGenModule &IGM, AbstractFunctionDecl *theMethod);

Expand Down
51 changes: 51 additions & 0 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,57 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"function");
}
}

// TODO: Impose additional constraints when partial_apply when the
// -disable-sil-partial-apply flag is enabled. We want to reduce
// partial_apply to being only a means of associating a closure invocation
// function with its context.
//
// When we reach that point, we should be able to more deeply redesign
// PartialApplyInst to simplify the representation to carry a single
// argument.
if (PAI->getModule().getOptions().DisableSILPartialApply) {
// Should only be one context argument.
require(PAI->getArguments().size() == 1,
"partial_apply should have a single context argument");

// Callee should already have the thin convention, and result should be
// thick.
require(resultInfo->getRepresentation() ==
SILFunctionTypeRepresentation::Thick,
"partial_apply result should have thick convention");
require(PAI->getCallee()->getType().castTo<SILFunctionType>()
->getRepresentation() ==
SILFunctionTypeRepresentation::Thin,
"partial_apply callee should have thin convention");

// TODO: Check that generic signature matches box's generic signature,
// once we have boxes with generic signatures.
require(!PAI->getCalleeFunction()->getGenericEnvironment(),
"partial_apply context must capture generic environment for "
"callee");

// Result's callee convention should match context argument's convention.
require(substTy->getParameters().back().getConvention()
== resultInfo->getCalleeConvention(),
"partial_apply context argument must have the same convention "
"as the resulting function's callee convention");

auto isSwiftRefcounted = [](SILType t) -> bool {
if (t.is<SILBoxType>())
return true;
if (t.getSwiftRValueType() == t.getASTContext().TheNativeObjectType)
return true;
if (auto clas = t.getClassOrBoundGenericClass())
// Must be a class defined in Swift.
return clas->hasKnownSwiftImplementation();
return false;
};

// The context argument must be a swift-refcounted box or class.
require(isSwiftRefcounted(PAI->getArguments().front()->getType()),
"partial_apply context argument must be swift-refcounted");
}
}

void checkBuiltinInst(BuiltinInst *BI) {
Expand Down
34 changes: 34 additions & 0 deletions test/SIL/restricted-partial-apply.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// RUN: %target-swift-frontend -module-name main -disable-sil-partial-apply -emit-sil -verify %s
sil_stage canonical
import Builtin

class C {}

sil @native_object_context : $@convention(thin) (@owned Builtin.NativeObject) -> ()
sil @box_context : $@convention(thin) (@owned @box Builtin.Word) -> ()
sil @class_context : $@convention(thin) (@owned C) -> ()

sil @g_native_object_context : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
sil @g_box_context : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
sil @g_class_context : $@convention(thin) (@guaranteed C) -> ()

sil @limited_partial_applies : $@convention(thin) (Builtin.NativeObject, @box Builtin.Word, C) -> () {
entry(%0 : $Builtin.NativeObject, %1 : $@box Builtin.Word, %2 : $C):
%a = function_ref @native_object_context : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%b = function_ref @box_context : $@convention(thin) (@owned @box Builtin.Word) -> ()
%c = function_ref @class_context : $@convention(thin) (@owned C) -> ()

%d = function_ref @g_native_object_context : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
%e = function_ref @g_box_context : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
%f = function_ref @g_class_context : $@convention(thin) (@guaranteed C) -> ()

%g = partial_apply %a(%0) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
%h = partial_apply %b(%1) : $@convention(thin) (@owned @box Builtin.Word) -> ()
%i = partial_apply %c(%2) : $@convention(thin) (@owned C) -> ()

%j = partial_apply [callee_guaranteed] %d(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
%k = partial_apply [callee_guaranteed] %e(%1) : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
%l = partial_apply [callee_guaranteed] %f(%2) : $@convention(thin) (@guaranteed C) -> ()

return undef : $()
}