Skip to content
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
20 changes: 20 additions & 0 deletions include/swift/Runtime/RuntimeFunctions.def
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,26 @@ FUNCTION(GetFunctionMetadataDifferentiable,
TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadOnly))

// Metadata *
// swift_getFunctionTypeMetadataGlobalActor(unsigned long flags,
// unsigned long diffKind,
// const Metadata **parameters,
// const uint32_t *parameterFlags,
// const Metadata *result,
// const Metadata *globalActor);
FUNCTION(GetFunctionMetadataGlobalActor,
swift_getFunctionTypeMetadataGlobalActor,
C_CC, AlwaysAvailable,
RETURNS(TypeMetadataPtrTy),
ARGS(SizeTy,
SizeTy,
TypeMetadataPtrTy->getPointerTo(0),
Int32Ty->getPointerTo(0),
TypeMetadataPtrTy,
TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadOnly))


// Metadata *swift_getFunctionTypeMetadata0(unsigned long flags,
// const Metadata *resultMetadata);
FUNCTION(GetFunctionMetadata0, swift_getFunctionTypeMetadata0,
Expand Down
85 changes: 53 additions & 32 deletions lib/IRGen/MetadataRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1445,15 +1445,20 @@ namespace {
.withThrows(type->isThrowing())
.withParameterFlags(hasParameterFlags)
.withEscaping(isEscaping)
.withDifferentiable(type->isDifferentiable());
.withDifferentiable(type->isDifferentiable())
.withGlobalActor(!type->getGlobalActor().isNull());

auto flagsVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
flags.getIntValue());
llvm::Value *diffKindVal = nullptr;
if (type->isDifferentiable()) {
assert(metadataDifferentiabilityKind.isDifferentiable());
diffKindVal = llvm::ConstantInt::get(IGF.IGM.SizeTy,
flags.getIntValue());
diffKindVal = llvm::ConstantInt::get(
IGF.IGM.SizeTy, metadataDifferentiabilityKind.getIntValue());
} else if (type->getGlobalActor()) {
diffKindVal = llvm::ConstantInt::get(
IGF.IGM.SizeTy,
FunctionMetadataDifferentiabilityKind::NonDifferentiable);
}

auto collectParameters =
Expand Down Expand Up @@ -1507,56 +1512,65 @@ namespace {
case 1:
case 2:
case 3: {
if (!hasParameterFlags && !type->isDifferentiable()) {
if (!hasParameterFlags && !type->isDifferentiable() &&
!type->getGlobalActor()) {
llvm::SmallVector<llvm::Value *, 8> arguments;
auto *metadataFn = constructSimpleCall(arguments);
auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
call->setDoesNotThrow();
return setLocal(CanType(type), MetadataResponse::forComplete(call));
}

// If function type has parameter flags or is differentiable, let's emit
// the most general function to retrieve them.
// If function type has parameter flags or is differentiable or has a
// global actor, emit the most general function to retrieve them.
LLVM_FALLTHROUGH;
}

default:
assert(!params.empty() || type->isDifferentiable() &&
assert((!params.empty() || type->isDifferentiable() ||
type->getGlobalActor()) &&
"0 parameter case should be specialized unless it is a "
"differentiable function");
"differentiable function or has a global actor");

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

arguments.push_back(flagsVal);

if (type->isDifferentiable()) {
assert(diffKindVal);
if (diffKindVal) {
arguments.push_back(diffKindVal);
}

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

auto arrayTy =
llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, numParams);
Address parameters = IGF.createAlloca(
arrayTy, IGF.IGM.getTypeMetadataAlignment(), "function-parameters");

IGF.Builder.CreateLifetimeStart(parameters,
IGF.IGM.getPointerSize() * numParams);

collectParameters([&](unsigned i, llvm::Value *typeRef,
ParameterFlags flags) {
auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
IGF.IGM.getPointerSize());
IGF.Builder.CreateStore(typeRef, argPtr);
if (i == 0)
arguments.push_back(argPtr.getAddress());

if (hasParameterFlags)
flagsArr.addInt32(flags.getIntValue());
});
Address parameters;
if (!params.empty()) {
auto arrayTy =
llvm::ArrayType::get(IGF.IGM.TypeMetadataPtrTy, numParams);
parameters = IGF.createAlloca(
arrayTy, IGF.IGM.getTypeMetadataAlignment(), "function-parameters");

IGF.Builder.CreateLifetimeStart(parameters,
IGF.IGM.getPointerSize() * numParams);

collectParameters([&](unsigned i, llvm::Value *typeRef,
ParameterFlags flags) {
auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
IGF.IGM.getPointerSize());
IGF.Builder.CreateStore(typeRef, argPtr);
if (i == 0)
arguments.push_back(argPtr.getAddress());

if (hasParameterFlags)
flagsArr.addInt32(flags.getIntValue());
});
} else {
auto parametersPtr =
llvm::ConstantPointerNull::get(
IGF.IGM.TypeMetadataPtrTy->getPointerTo());
arguments.push_back(parametersPtr);
}

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

arguments.push_back(result);

auto *getMetadataFn = type->isDifferentiable()
? IGF.IGM.getGetFunctionMetadataDifferentiableFn()
: IGF.IGM.getGetFunctionMetadataFn();
if (Type globalActor = type->getGlobalActor()) {
arguments.push_back(
IGF.emitAbstractTypeMetadataRef(globalActor->getCanonicalType()));
}

auto *getMetadataFn = type->getGlobalActor()
? IGF.IGM.getGetFunctionMetadataGlobalActorFn()
: type->isDifferentiable()
? IGF.IGM.getGetFunctionMetadataDifferentiableFn()
: IGF.IGM.getGetFunctionMetadataFn();

auto call = IGF.Builder.CreateCall(getMetadataFn, arguments);
call->setDoesNotThrow();
Expand Down
56 changes: 55 additions & 1 deletion stdlib/public/Reflection/TypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,40 @@ class PrintTypeRef : public TypeRefVisitor<PrintTypeRef, void> {
break;
}

switch (F->getDifferentiabilityKind().Value) {
case FunctionMetadataDifferentiabilityKind::NonDifferentiable:
break;

case FunctionMetadataDifferentiabilityKind::Forward:
printField("differentiable", "forward");
break;

case FunctionMetadataDifferentiabilityKind::Reverse:
printField("differentiable", "reverse");
break;

case FunctionMetadataDifferentiabilityKind::Normal:
printField("differentiable", "normal");
break;

case FunctionMetadataDifferentiabilityKind::Linear:
printField("differentiable", "linear");
break;
}

if (auto globalActor = F->getGlobalActor()) {
fprintf(file, "\n");
Indent += 2;
printHeader("global-actor");
{
Indent += 2;
printRec(globalActor);
fprintf(file, ")");
Indent -= 2;
}
Indent += 2;
}

fprintf(file, "\n");
Indent += 2;
printHeader("parameters");
Expand Down Expand Up @@ -670,7 +704,27 @@ class DemanglingForTypeRef
funcNode->addChild(node, Dem);
}

// FIXME: Differentiability is missing
if (F->getFlags().isDifferentiable()) {
MangledDifferentiabilityKind mangledKind;
switch (F->getDifferentiabilityKind().Value) {
#define CASE(X) case FunctionMetadataDifferentiabilityKind::X: \
mangledKind = MangledDifferentiabilityKind::X; break;

CASE(NonDifferentiable)
CASE(Forward)
CASE(Reverse)
CASE(Normal)
CASE(Linear)
#undef CASE
}

funcNode->addChild(
Dem.createNode(
Node::Kind::DifferentiableFunctionType,
(Node::IndexType)mangledKind),
Dem);
}

if (F->getFlags().isThrowing())
funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem);
if (F->getFlags().isSendable()) {
Expand Down
5 changes: 5 additions & 0 deletions test/AutoDiff/validation-test/Inputs/AutoDiffTypes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import _Differentiation

public struct HasAutoDiffTypes {
public var aFunction: @differentiable(reverse) (Float) -> Float
}
1 change: 1 addition & 0 deletions test/AutoDiff/validation-test/Inputs/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// this file intentionally left blank
16 changes: 16 additions & 0 deletions test/AutoDiff/validation-test/reflection.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// REQUIRES: no_asan
// RUN: %empty-directory(%t)
import _Differentiation

// 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)
// 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

// RUN: %target-swift-reflection-dump -binary-filename %t/%target-library-name(TypesToReflect) | %FileCheck %s
// RUN: %target-swift-reflection-dump -binary-filename %t/TypesToReflect | %FileCheck %s

// CHECK: FIELDS:
// CHECK: =======
// CHECK: TypesToReflect.HasAutoDiffTypes
// CHECK: aFunction: @differentiable(reverse) (Swift.Float) -> Swift.Float
// CHECK: (function differentiable=reverse

22 changes: 22 additions & 0 deletions test/IRGen/global_actor_function_types.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// RUN: %target-swift-frontend -emit-ir -o - -primary-file %s | %FileCheck %s --check-prefix CHECK --check-prefix CHECK-%target-cpu
// REQUIRES: concurrency

import Swift
import _Concurrency

func globalActorMetatype<T>(_: T.Type) -> Any.Type {
typealias Fn = @MainActor () -> T
return Fn.self
}

// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc %swift.type* @"$s4test19globalActorMetatypeyypXpxmlF"
// CHECK: [[MAIN_ACTOR_RESPONSE:%[0-9]+]] = call swiftcc %swift.metadata_response @"$sScMMa"(i{{32|64}} 255)
// CHECK-NEXT: [[MAIN_ACTOR_METADATA:%[0-9]+]] = extractvalue %swift.metadata_response [[MAIN_ACTOR_RESPONSE]], 0
// 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]])
sil [ossa] @$s4test19globalActorMetatypeyypXpxmlF : $@convention(thin) <T> (@thick T.Type) -> @thick Any.Type {
bb0(%0 : $@thick T.Type):
%2 = metatype $@thin (@MainActor () -> T).Type
%3 = metatype $@thick (@MainActor () -> T).Type
%4 = init_existential_metatype %3 : $@thick (@MainActor () -> T).Type, $@thick Any.Type
return %4 : $@thick Any.Type
}
3 changes: 3 additions & 0 deletions test/Reflection/Inputs/ConcurrencyTypes.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public struct UsesConcurrency {
public var mainActorFunction: @MainActor () -> Void
}
25 changes: 25 additions & 0 deletions test/Reflection/typeref_decoding_concurrency.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// REQUIRES: no_asan
// REQUIRES: executable_test
// REQUIRES: concurrency
// REQUIRES: libdispatch

// rdar://76038845
// UNSUPPORTED: use_os_stdlib
// UNSUPPORTED: back_deployment_runtime

// RUN: %empty-directory(%t)

// 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)
// 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

// RUN: %target-swift-reflection-dump -binary-filename %t/%target-library-name(TypesToReflect) | %FileCheck %s
// RUN: %target-swift-reflection-dump -binary-filename %t/TypesToReflect | %FileCheck %s

// CHECK: FIELDS:
// CHECK: =======
// CHECK: TypesToReflect.UsesConcurrency
// CHECK: ------------------
// CHECK: mainActorFunction: @Swift.MainActor () -> ()
// CHECK: (function
// CHECK: (global-actor
// CHECK: (class Swift.MainActor))
8 changes: 8 additions & 0 deletions test/Runtime/demangleToMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ func f1_autoclosure(_: @autoclosure () -> Float) { }
func f1_escaping_autoclosure(_: @autoclosure @escaping () -> Float) { }
func f1_mainactor(_: @MainActor () -> Float) { }

func globalActorMetatypeFn<T>(_: T.Type) -> Any.Type {
typealias Fn = @MainActor () -> T
return Fn.self
}

DemangleToMetadataTests.test("function types") {
// Conventions
expectEqual(type(of: f0), _typeByName("yyc")!)
Expand Down Expand Up @@ -106,6 +111,9 @@ DemangleToMetadataTests.test("function types") {
expectEqual(
"(@MainActor () -> Float) -> ()",
String(describing: _typeByName("ySfyScMYcXEc")!))
typealias MainActorFn = @MainActor () -> Float
expectEqual(MainActorFn.self, _typeByName("SfyScMYcc")!)
expectEqual(MainActorFn.self, globalActorMetatypeFn(Float.self))
}

DemangleToMetadataTests.test("metatype types") {
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/global_actor_function_mangling.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 -enable-experimental-concurrency | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen %s -module-name test -swift-version 5 | %FileCheck %s
// REQUIRES: concurrency

// Declarations don't mangle global actor types.
Expand Down