Skip to content

Commit b51cf74

Browse files
authored
Merge pull request #5213 from jckarter/simplify-partial-apply
2 parents 3797db2 + b4041a5 commit b51cf74

File tree

10 files changed

+103
-13
lines changed

10 files changed

+103
-13
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3268,6 +3268,11 @@ class ClassDecl : public NominalTypeDecl {
32683268
bool usesObjCGenericsModel() const {
32693269
return isObjC() && hasClangNode() && isGenericContext();
32703270
}
3271+
3272+
/// True if the class is known to be implemented in Swift.
3273+
bool hasKnownSwiftImplementation() const {
3274+
return !hasClangNode();
3275+
}
32713276
};
32723277

32733278

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class SILOptions {
108108
/// conventions.
109109
bool EnableGuaranteedClosureContexts = false;
110110

111+
/// Don't generate code using partial_apply in SIL generation.
112+
bool DisableSILPartialApply = false;
113+
111114
/// The name of the SIL outputfile if compiled with SIL debugging (-gsil).
112115
std::string SILOutputFileNameForDebugging;
113116
};

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ def disable_arc_opts : Flag<["-"], "disable-arc-opts">,
163163
def enable_guaranteed_closure_contexts : Flag<["-"], "enable-guaranteed-closure-contexts">,
164164
HelpText<"Use @guaranteed convention for closure context">;
165165

166+
def disable_sil_partial_apply : Flag<["-"], "disable-sil-partial-apply">,
167+
HelpText<"Disable use of partial_apply in SIL generation">;
168+
166169
def remove_runtime_asserts : Flag<["-"], "remove-runtime-asserts">,
167170
HelpText<"Remove runtime asserts.">;
168171

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
11301130
Opts.EmitProfileCoverageMapping |= Args.hasArg(OPT_profile_coverage_mapping);
11311131
Opts.EnableGuaranteedClosureContexts |=
11321132
Args.hasArg(OPT_enable_guaranteed_closure_contexts);
1133+
Opts.DisableSILPartialApply |=
1134+
Args.hasArg(OPT_disable_sil_partial_apply);
11331135

11341136
if (Args.hasArg(OPT_debug_on_sil)) {
11351137
// Derive the name of the SIL file for debugging from

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
151151

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

157157
switch (mode) {

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ReferenceCounting irgen::getReferenceCountingForClass(IRGenModule &IGM,
7272
// NOTE: if you change this, change Type::usesNativeReferenceCounting.
7373
// If the root class is implemented in swift, then we have a swift
7474
// refcount; otherwise, we have an ObjC refcount.
75-
if (hasKnownSwiftImplementation(IGM, getRootClass(theClass)))
75+
if (getRootClass(theClass)->hasKnownSwiftImplementation())
7676
return ReferenceCounting::Native;
7777

7878
return ReferenceCounting::ObjC;
@@ -83,7 +83,7 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
8383
CanType type) {
8484
if (auto theClass = type->getClassOrBoundGenericClass()) {
8585
// We can access the isas of pure Swift classes directly.
86-
if (hasKnownSwiftImplementation(IGM, getRootClass(theClass)))
86+
if (getRootClass(theClass)->hasKnownSwiftImplementation())
8787
return IsaEncoding::Pointer;
8888
// For ObjC or mixed classes, we need to use object_getClass.
8989
return IsaEncoding::ObjC;

lib/IRGen/GenMeta.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -435,12 +435,7 @@ bool irgen::hasKnownSwiftMetadata(IRGenModule &IGM, ClassDecl *theClass) {
435435
// is enough to conclusively force us into a slower path.
436436
// Eventually we might have an attribute here or something based on
437437
// the deployment target.
438-
return hasKnownSwiftImplementation(IGM, theClass);
439-
}
440-
441-
/// Is the given class known to have an implementation in Swift?
442-
bool irgen::hasKnownSwiftImplementation(IRGenModule &IGM, ClassDecl *theClass) {
443-
return !theClass->hasClangNode();
438+
return theClass->hasKnownSwiftImplementation();
444439
}
445440

446441
/// Is the given method known to be callable by vtable lookup?
@@ -451,7 +446,7 @@ bool irgen::hasKnownVTableEntry(IRGenModule &IGM,
451446
if (!theClass) {
452447
return false;
453448
}
454-
return hasKnownSwiftImplementation(IGM, theClass);
449+
return theClass->hasKnownSwiftImplementation();
455450
}
456451

457452
/// Is it basically trivial to access the given metadata? If so, we don't

lib/IRGen/GenMeta.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ namespace irgen {
6262
/// metadata?
6363
bool hasKnownSwiftMetadata(IRGenModule &IGM, CanType theType);
6464

65-
/// Is the given class known to have an implementation in Swift?
66-
bool hasKnownSwiftImplementation(IRGenModule &IGM, ClassDecl *theClass);
67-
6865
/// Is the given method known to be callable by vtable dispatch?
6966
bool hasKnownVTableEntry(IRGenModule &IGM, AbstractFunctionDecl *theMethod);
7067

lib/SIL/SILVerifier.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,57 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
996996
"function");
997997
}
998998
}
999+
1000+
// TODO: Impose additional constraints when partial_apply when the
1001+
// -disable-sil-partial-apply flag is enabled. We want to reduce
1002+
// partial_apply to being only a means of associating a closure invocation
1003+
// function with its context.
1004+
//
1005+
// When we reach that point, we should be able to more deeply redesign
1006+
// PartialApplyInst to simplify the representation to carry a single
1007+
// argument.
1008+
if (PAI->getModule().getOptions().DisableSILPartialApply) {
1009+
// Should only be one context argument.
1010+
require(PAI->getArguments().size() == 1,
1011+
"partial_apply should have a single context argument");
1012+
1013+
// Callee should already have the thin convention, and result should be
1014+
// thick.
1015+
require(resultInfo->getRepresentation() ==
1016+
SILFunctionTypeRepresentation::Thick,
1017+
"partial_apply result should have thick convention");
1018+
require(PAI->getCallee()->getType().castTo<SILFunctionType>()
1019+
->getRepresentation() ==
1020+
SILFunctionTypeRepresentation::Thin,
1021+
"partial_apply callee should have thin convention");
1022+
1023+
// TODO: Check that generic signature matches box's generic signature,
1024+
// once we have boxes with generic signatures.
1025+
require(!PAI->getCalleeFunction()->getGenericEnvironment(),
1026+
"partial_apply context must capture generic environment for "
1027+
"callee");
1028+
1029+
// Result's callee convention should match context argument's convention.
1030+
require(substTy->getParameters().back().getConvention()
1031+
== resultInfo->getCalleeConvention(),
1032+
"partial_apply context argument must have the same convention "
1033+
"as the resulting function's callee convention");
1034+
1035+
auto isSwiftRefcounted = [](SILType t) -> bool {
1036+
if (t.is<SILBoxType>())
1037+
return true;
1038+
if (t.getSwiftRValueType() == t.getASTContext().TheNativeObjectType)
1039+
return true;
1040+
if (auto clas = t.getClassOrBoundGenericClass())
1041+
// Must be a class defined in Swift.
1042+
return clas->hasKnownSwiftImplementation();
1043+
return false;
1044+
};
1045+
1046+
// The context argument must be a swift-refcounted box or class.
1047+
require(isSwiftRefcounted(PAI->getArguments().front()->getType()),
1048+
"partial_apply context argument must be swift-refcounted");
1049+
}
9991050
}
10001051

10011052
void checkBuiltinInst(BuiltinInst *BI) {

test/SIL/restricted-partial-apply.sil

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-frontend -module-name main -disable-sil-partial-apply -emit-sil -verify %s
2+
sil_stage canonical
3+
import Builtin
4+
5+
class C {}
6+
7+
sil @native_object_context : $@convention(thin) (@owned Builtin.NativeObject) -> ()
8+
sil @box_context : $@convention(thin) (@owned @box Builtin.Word) -> ()
9+
sil @class_context : $@convention(thin) (@owned C) -> ()
10+
11+
sil @g_native_object_context : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
12+
sil @g_box_context : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
13+
sil @g_class_context : $@convention(thin) (@guaranteed C) -> ()
14+
15+
sil @limited_partial_applies : $@convention(thin) (Builtin.NativeObject, @box Builtin.Word, C) -> () {
16+
entry(%0 : $Builtin.NativeObject, %1 : $@box Builtin.Word, %2 : $C):
17+
%a = function_ref @native_object_context : $@convention(thin) (@owned Builtin.NativeObject) -> ()
18+
%b = function_ref @box_context : $@convention(thin) (@owned @box Builtin.Word) -> ()
19+
%c = function_ref @class_context : $@convention(thin) (@owned C) -> ()
20+
21+
%d = function_ref @g_native_object_context : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
22+
%e = function_ref @g_box_context : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
23+
%f = function_ref @g_class_context : $@convention(thin) (@guaranteed C) -> ()
24+
25+
%g = partial_apply %a(%0) : $@convention(thin) (@owned Builtin.NativeObject) -> ()
26+
%h = partial_apply %b(%1) : $@convention(thin) (@owned @box Builtin.Word) -> ()
27+
%i = partial_apply %c(%2) : $@convention(thin) (@owned C) -> ()
28+
29+
%j = partial_apply [callee_guaranteed] %d(%0) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> ()
30+
%k = partial_apply [callee_guaranteed] %e(%1) : $@convention(thin) (@guaranteed @box Builtin.Word) -> ()
31+
%l = partial_apply [callee_guaranteed] %f(%2) : $@convention(thin) (@guaranteed C) -> ()
32+
33+
return undef : $()
34+
}

0 commit comments

Comments
 (0)