Skip to content

Commit b3cd558

Browse files
authored
Merge pull request #37769 from DougGregor/extended-function-type-reflection
Finish IRGen and reflection for global-actor-qualified and differentiable function types
2 parents 40b084e + a140364 commit b3cd558

File tree

11 files changed

+209
-34
lines changed

11 files changed

+209
-34
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,26 @@ FUNCTION(GetFunctionMetadataDifferentiable,
591591
TypeMetadataPtrTy),
592592
ATTRS(NoUnwind, ReadOnly))
593593

594+
// Metadata *
595+
// swift_getFunctionTypeMetadataGlobalActor(unsigned long flags,
596+
// unsigned long diffKind,
597+
// const Metadata **parameters,
598+
// const uint32_t *parameterFlags,
599+
// const Metadata *result,
600+
// const Metadata *globalActor);
601+
FUNCTION(GetFunctionMetadataGlobalActor,
602+
swift_getFunctionTypeMetadataGlobalActor,
603+
C_CC, AlwaysAvailable,
604+
RETURNS(TypeMetadataPtrTy),
605+
ARGS(SizeTy,
606+
SizeTy,
607+
TypeMetadataPtrTy->getPointerTo(0),
608+
Int32Ty->getPointerTo(0),
609+
TypeMetadataPtrTy,
610+
TypeMetadataPtrTy),
611+
ATTRS(NoUnwind, ReadOnly))
612+
613+
594614
// Metadata *swift_getFunctionTypeMetadata0(unsigned long flags,
595615
// const Metadata *resultMetadata);
596616
FUNCTION(GetFunctionMetadata0, swift_getFunctionTypeMetadata0,

lib/IRGen/MetadataRequest.cpp

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1445,15 +1445,20 @@ namespace {
14451445
.withThrows(type->isThrowing())
14461446
.withParameterFlags(hasParameterFlags)
14471447
.withEscaping(isEscaping)
1448-
.withDifferentiable(type->isDifferentiable());
1448+
.withDifferentiable(type->isDifferentiable())
1449+
.withGlobalActor(!type->getGlobalActor().isNull());
14491450

14501451
auto flagsVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
14511452
flags.getIntValue());
14521453
llvm::Value *diffKindVal = nullptr;
14531454
if (type->isDifferentiable()) {
14541455
assert(metadataDifferentiabilityKind.isDifferentiable());
1455-
diffKindVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
1456-
flags.getIntValue());
1456+
diffKindVal = llvm::ConstantInt::get(
1457+
IGF.IGM.SizeTy, metadataDifferentiabilityKind.getIntValue());
1458+
} else if (type->getGlobalActor()) {
1459+
diffKindVal = llvm::ConstantInt::get(
1460+
IGF.IGM.SizeTy,
1461+
FunctionMetadataDifferentiabilityKind::NonDifferentiable);
14571462
}
14581463

14591464
auto collectParameters =
@@ -1507,56 +1512,65 @@ namespace {
15071512
case 1:
15081513
case 2:
15091514
case 3: {
1510-
if (!hasParameterFlags && !type->isDifferentiable()) {
1515+
if (!hasParameterFlags && !type->isDifferentiable() &&
1516+
!type->getGlobalActor()) {
15111517
llvm::SmallVector<llvm::Value *, 8> arguments;
15121518
auto *metadataFn = constructSimpleCall(arguments);
15131519
auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
15141520
call->setDoesNotThrow();
15151521
return setLocal(CanType(type), MetadataResponse::forComplete(call));
15161522
}
15171523

1518-
// If function type has parameter flags or is differentiable, let's emit
1519-
// the most general function to retrieve them.
1524+
// If function type has parameter flags or is differentiable or has a
1525+
// global actor, emit the most general function to retrieve them.
15201526
LLVM_FALLTHROUGH;
15211527
}
15221528

15231529
default:
1524-
assert(!params.empty() || type->isDifferentiable() &&
1530+
assert((!params.empty() || type->isDifferentiable() ||
1531+
type->getGlobalActor()) &&
15251532
"0 parameter case should be specialized unless it is a "
1526-
"differentiable function");
1533+
"differentiable function or has a global actor");
15271534

15281535
auto *const Int32Ptr = IGF.IGM.Int32Ty->getPointerTo();
15291536
llvm::SmallVector<llvm::Value *, 8> arguments;
15301537

15311538
arguments.push_back(flagsVal);
15321539

1533-
if (type->isDifferentiable()) {
1534-
assert(diffKindVal);
1540+
if (diffKindVal) {
15351541
arguments.push_back(diffKindVal);
15361542
}
15371543

15381544
ConstantInitBuilder paramFlags(IGF.IGM);
15391545
auto flagsArr = paramFlags.beginArray();
15401546

1541-
auto arrayTy =
1542-
llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, numParams);
1543-
Address parameters = IGF.createAlloca(
1544-
arrayTy, IGF.IGM.getTypeMetadataAlignment(), "function-parameters");
1545-
1546-
IGF.Builder.CreateLifetimeStart(parameters,
1547-
IGF.IGM.getPointerSize() * numParams);
1548-
1549-
collectParameters([&](unsigned i, llvm::Value *typeRef,
1550-
ParameterFlags flags) {
1551-
auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
1552-
IGF.IGM.getPointerSize());
1553-
IGF.Builder.CreateStore(typeRef, argPtr);
1554-
if (i == 0)
1555-
arguments.push_back(argPtr.getAddress());
1556-
1557-
if (hasParameterFlags)
1558-
flagsArr.addInt32(flags.getIntValue());
1559-
});
1547+
Address parameters;
1548+
if (!params.empty()) {
1549+
auto arrayTy =
1550+
llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, numParams);
1551+
parameters = IGF.createAlloca(
1552+
arrayTy, IGF.IGM.getTypeMetadataAlignment(), "function-parameters");
1553+
1554+
IGF.Builder.CreateLifetimeStart(parameters,
1555+
IGF.IGM.getPointerSize() * numParams);
1556+
1557+
collectParameters([&](unsigned i, llvm::Value *typeRef,
1558+
ParameterFlags flags) {
1559+
auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
1560+
IGF.IGM.getPointerSize());
1561+
IGF.Builder.CreateStore(typeRef, argPtr);
1562+
if (i == 0)
1563+
arguments.push_back(argPtr.getAddress());
1564+
1565+
if (hasParameterFlags)
1566+
flagsArr.addInt32(flags.getIntValue());
1567+
});
1568+
} else {
1569+
auto parametersPtr =
1570+
llvm::ConstantPointerNull::get(
1571+
IGF.IGM.TypeMetadataPtrTy->getPointerTo());
1572+
arguments.push_back(parametersPtr);
1573+
}
15601574

15611575
if (hasParameterFlags) {
15621576
auto *flagsVar = flagsArr.finishAndCreateGlobal(
@@ -1570,9 +1584,16 @@ namespace {
15701584

15711585
arguments.push_back(result);
15721586

1573-
auto *getMetadataFn = type->isDifferentiable()
1574-
? IGF.IGM.getGetFunctionMetadataDifferentiableFn()
1575-
: IGF.IGM.getGetFunctionMetadataFn();
1587+
if (Type globalActor = type->getGlobalActor()) {
1588+
arguments.push_back(
1589+
IGF.emitAbstractTypeMetadataRef(globalActor->getCanonicalType()));
1590+
}
1591+
1592+
auto *getMetadataFn = type->getGlobalActor()
1593+
? IGF.IGM.getGetFunctionMetadataGlobalActorFn()
1594+
: type->isDifferentiable()
1595+
? IGF.IGM.getGetFunctionMetadataDifferentiableFn()
1596+
: IGF.IGM.getGetFunctionMetadataFn();
15761597

15771598
auto call = IGF.Builder.CreateCall(getMetadataFn, arguments);
15781599
call->setDoesNotThrow();

stdlib/public/Reflection/TypeRef.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,40 @@ class PrintTypeRef : public TypeRefVisitor<PrintTypeRef, void> {
137137
break;
138138
}
139139

140+
switch (F->getDifferentiabilityKind().Value) {
141+
case FunctionMetadataDifferentiabilityKind::NonDifferentiable:
142+
break;
143+
144+
case FunctionMetadataDifferentiabilityKind::Forward:
145+
printField("differentiable", "forward");
146+
break;
147+
148+
case FunctionMetadataDifferentiabilityKind::Reverse:
149+
printField("differentiable", "reverse");
150+
break;
151+
152+
case FunctionMetadataDifferentiabilityKind::Normal:
153+
printField("differentiable", "normal");
154+
break;
155+
156+
case FunctionMetadataDifferentiabilityKind::Linear:
157+
printField("differentiable", "linear");
158+
break;
159+
}
160+
161+
if (auto globalActor = F->getGlobalActor()) {
162+
fprintf(file, "\n");
163+
Indent += 2;
164+
printHeader("global-actor");
165+
{
166+
Indent += 2;
167+
printRec(globalActor);
168+
fprintf(file, ")");
169+
Indent -= 2;
170+
}
171+
Indent += 2;
172+
}
173+
140174
fprintf(file, "\n");
141175
Indent += 2;
142176
printHeader("parameters");
@@ -670,7 +704,27 @@ class DemanglingForTypeRef
670704
funcNode->addChild(node, Dem);
671705
}
672706

673-
// FIXME: Differentiability is missing
707+
if (F->getFlags().isDifferentiable()) {
708+
MangledDifferentiabilityKind mangledKind;
709+
switch (F->getDifferentiabilityKind().Value) {
710+
#define CASE(X) case FunctionMetadataDifferentiabilityKind::X: \
711+
mangledKind = MangledDifferentiabilityKind::X; break;
712+
713+
CASE(NonDifferentiable)
714+
CASE(Forward)
715+
CASE(Reverse)
716+
CASE(Normal)
717+
CASE(Linear)
718+
#undef CASE
719+
}
720+
721+
funcNode->addChild(
722+
Dem.createNode(
723+
Node::Kind::DifferentiableFunctionType,
724+
(Node::IndexType)mangledKind),
725+
Dem);
726+
}
727+
674728
if (F->getFlags().isThrowing())
675729
funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
676730
if (F->getFlags().isSendable()) {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import _Differentiation
2+
3+
public struct HasAutoDiffTypes {
4+
public var aFunction: @differentiable(reverse) (Float) -> Float
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// this file intentionally left blank
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: no_asan
2+
// RUN: %empty-directory(%t)
3+
import _Differentiation
4+
5+
// RUN: %target-build-swift -Xfrontend -enable-anonymous-context-mangled-names %S/Inputs/AutoDiffTypes.swift -parse-as-library -emit-module -emit-library -module-name TypesToReflect -o %t/%target-library-name(TypesToReflect)
6+
// RUN: %target-build-swift -Xfrontend -enable-anonymous-context-mangled-names %S/Inputs/AutoDiffTypes.swift %S/Inputs/main.swift -emit-module -emit-executable -module-name TypesToReflect -o %t/TypesToReflect
7+
8+
// RUN: %target-swift-reflection-dump -binary-filename %t/%target-library-name(TypesToReflect) | %FileCheck %s
9+
// RUN: %target-swift-reflection-dump -binary-filename %t/TypesToReflect | %FileCheck %s
10+
11+
// CHECK: FIELDS:
12+
// CHECK: =======
13+
// CHECK: TypesToReflect.HasAutoDiffTypes
14+
// CHECK: aFunction: @differentiable(reverse) (Swift.Float) -> Swift.Float
15+
// CHECK: (function differentiable=reverse
16+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -emit-ir -o - -primary-file %s | %FileCheck %s --check-prefix CHECK --check-prefix CHECK-%target-cpu
2+
// REQUIRES: concurrency
3+
4+
import Swift
5+
import _Concurrency
6+
7+
func globalActorMetatype<T>(_: T.Type) -> Any.Type {
8+
typealias Fn = @MainActor () -> T
9+
return Fn.self
10+
}
11+
12+
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @"$s4test19globalActorMetatypeyypXpxmlF"
13+
// CHECK: [[MAIN_ACTOR_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$sScMMa"(i{{32|64}} 255)
14+
// CHECK-NEXT: [[MAIN_ACTOR_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[MAIN_ACTOR_RESPONSE]], 0
15+
// CHECK: call %swift.type* @swift_getFunctionTypeMetadataGlobalActor(i{{32|64}} 335544320, i{{32|64}} 0, %swift.type** null, i32* null, %swift.type* %T, %swift.type* [[MAIN_ACTOR_METADATA]])
16+
sil [ossa] @$s4test19globalActorMetatypeyypXpxmlF : $@convention(thin) <T> (@thick T.Type) -> @thick Any.Type {
17+
bb0(%0 : $@thick T.Type):
18+
%2 = metatype $@thin (@MainActor () -> T).Type
19+
%3 = metatype $@thick (@MainActor () -> T).Type
20+
%4 = init_existential_metatype %3 : $@thick (@MainActor () -> T).Type, $@thick Any.Type
21+
return %4 : $@thick Any.Type
22+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public struct UsesConcurrency {
2+
public var mainActorFunction: @MainActor () -> Void
3+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// REQUIRES: no_asan
2+
// REQUIRES: executable_test
3+
// REQUIRES: concurrency
4+
// REQUIRES: libdispatch
5+
6+
// rdar://76038845
7+
// UNSUPPORTED: use_os_stdlib
8+
// UNSUPPORTED: back_deployment_runtime
9+
10+
// RUN: %empty-directory(%t)
11+
12+
// RUN: %target-build-swift -Xfrontend -enable-anonymous-context-mangled-names %S/Inputs/ConcurrencyTypes.swift -parse-as-library -emit-module -emit-library -module-name TypesToReflect -o %t/%target-library-name(TypesToReflect)
13+
// RUN: %target-build-swift -Xfrontend -enable-anonymous-context-mangled-names %S/Inputs/ConcurrencyTypes.swift %S/Inputs/main.swift -emit-module -emit-executable -module-name TypesToReflect -o %t/TypesToReflect
14+
15+
// RUN: %target-swift-reflection-dump -binary-filename %t/%target-library-name(TypesToReflect) | %FileCheck %s
16+
// RUN: %target-swift-reflection-dump -binary-filename %t/TypesToReflect | %FileCheck %s
17+
18+
// CHECK: FIELDS:
19+
// CHECK: =======
20+
// CHECK: TypesToReflect.UsesConcurrency
21+
// CHECK: ------------------
22+
// CHECK: mainActorFunction: @Swift.MainActor () -> ()
23+
// CHECK: (function
24+
// CHECK: (global-actor
25+
// CHECK: (class Swift.MainActor))

test/Runtime/demangleToMetadata.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ func f1_autoclosure(_: @autoclosure () -> Float) { }
5555
func f1_escaping_autoclosure(_: @autoclosure @escaping () -> Float) { }
5656
func f1_mainactor(_: @MainActor () -> Float) { }
5757

58+
func globalActorMetatypeFn<T>(_: T.Type) -> Any.Type {
59+
typealias Fn = @MainActor () -> T
60+
return Fn.self
61+
}
62+
5863
DemangleToMetadataTests.test("function types") {
5964
// Conventions
6065
expectEqual(type(of: f0), _typeByName("yyc")!)
@@ -106,6 +111,9 @@ DemangleToMetadataTests.test("function types") {
106111
expectEqual(
107112
"(@MainActor () -> Float) -> ()",
108113
String(describing: _typeByName("ySfyScMYcXEc")!))
114+
typealias MainActorFn = @MainActor () -> Float
115+
expectEqual(MainActorFn.self, _typeByName("SfyScMYcc")!)
116+
expectEqual(MainActorFn.self, globalActorMetatypeFn(Float.self))
109117
}
110118

111119
DemangleToMetadataTests.test("metatype types") {

test/SILGen/global_actor_function_mangling.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 -enable-experimental-concurrency | %FileCheck %s
1+
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 | %FileCheck %s
22
// REQUIRES: concurrency
33

44
// Declarations don't mangle global actor types.

0 commit comments

Comments
 (0)