Skip to content

@DougGregor Implement (de-)mangling and type metadata for global actor function types #37759

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
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
3 changes: 2 additions & 1 deletion docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ Types
C-TYPE is mangled according to the Itanium ABI, and prefixed with the length.
Non-ASCII identifiers are preserved as-is; we do not use Punycode.

function-signature ::= params-type params-type async? sendable? throws? differentiable? // results and parameters
function-signature ::= params-type params-type async? sendable? throws? differentiable? global-actor? // results and parameters

params-type ::= type 'z'? 'h'? // tuple in case of multiple parameters or a single parameter with a single tuple type
// with optional inout convention, shared convention. parameters don't have labels,
Expand All @@ -599,6 +599,7 @@ Types
#if SWIFT_RUNTIME_VERSION >= 5.5
async ::= 'Ya' // 'async' annotation on function types
sendable ::= 'Yb' // @Sendable on function types
global-actor :: = type 'Yc' // Global actor on function type
#endif
throws ::= 'K' // 'throws' annotation on function types
differentiable ::= 'Yjf' // @differentiable(_forward) on function type
Expand Down
26 changes: 26 additions & 0 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,7 @@ struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
bool isDifferentiable() const { return Flags.isDifferentiable(); }
bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
bool isEscaping() const { return Flags.isEscaping(); }
bool hasGlobalActor() const { return Flags.hasGlobalActor(); }

static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);

Expand Down Expand Up @@ -1702,6 +1703,31 @@ struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
return TargetFunctionMetadataDifferentiabilityKind<StoredSize>
::NonDifferentiable;
}

ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> *
getGlobalActorAddr() {
assert(hasGlobalActor());

void *endAddr =
isDifferentiable()
? reinterpret_cast<void *>(getDifferentiabilityKindAddress() + 1) :
hasParameterFlags()
? reinterpret_cast<void *>(getParameterFlags() + getNumParameters()) :
reinterpret_cast<void *>(getParameters() + getNumParameters());
return reinterpret_cast<
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> *>(
llvm::alignAddr(
endAddr, llvm::Align(alignof(typename Runtime::StoredPointer))));
}

ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>
getGlobalActor() const {
if (!hasGlobalActor())
return ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>();

return *const_cast<TargetFunctionTypeMetadata<Runtime> *>(this)
->getGlobalActorAddr();
}
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;

Expand Down
12 changes: 12 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,8 +834,10 @@ class TargetFunctionTypeFlags {
ParamFlagsMask = 0x02000000U,
EscapingMask = 0x04000000U,
DifferentiableMask = 0x08000000U,
GlobalActorMask = 0x10000000U,
AsyncMask = 0x20000000U,
SendableMask = 0x40000000U,
// NOTE: The next bit will need to introduce a separate flags word.
};
int_type Data;

Expand Down Expand Up @@ -891,6 +893,12 @@ class TargetFunctionTypeFlags {
(isSendable ? SendableMask : 0));
}

constexpr TargetFunctionTypeFlags<int_type>
withGlobalActor(bool globalActor) const {
return TargetFunctionTypeFlags<int_type>(
(Data & ~GlobalActorMask) | (globalActor ? GlobalActorMask : 0));
}

unsigned getNumParameters() const { return Data & NumParametersMask; }

FunctionMetadataConvention getConvention() const {
Expand All @@ -915,6 +923,10 @@ class TargetFunctionTypeFlags {
return bool (Data & DifferentiableMask);
}

bool hasGlobalActor() const {
return bool (Data & GlobalActorMask);
}

int_type getIntValue() const {
return Data;
}
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/ASTDemangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class ASTBuilder {
Type createFunctionType(
ArrayRef<Demangle::FunctionParam<Type>> params,
Type output, FunctionTypeFlags flags,
FunctionMetadataDifferentiabilityKind diffKind);
FunctionMetadataDifferentiabilityKind diffKind, Type globalActor);

Type createImplFunctionType(
Demangle::ImplParameterConvention calleeConvention,
Expand Down
1 change: 1 addition & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ NODE(ErrorType)
NODE(EscapingAutoClosureType)
NODE(NoEscapeFunctionType)
NODE(ConcurrentFunctionType)
NODE(GlobalActorFunctionType)
NODE(DifferentiableFunctionType)
NODE(ExistentialMetatype)
CONTEXT_NODE(ExplicitClosure)
Expand Down
19 changes: 18 additions & 1 deletion include/swift/Demangling/TypeDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,23 @@ class TypeDecoder {
++firstChildIdx;
}

BuiltType globalActorType = BuiltType();
if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::GlobalActorFunctionType) {
auto child = Node->getChild(firstChildIdx);
if (child->getNumChildren() < 1) {
return MAKE_NODE_TYPE_ERROR0(child,
"Global actor node is missing child");
}

auto globalActorResult = decodeMangledType(child->getChild(0));
if (globalActorResult.isError())
return globalActorResult;

globalActorType = globalActorResult.getType();
++firstChildIdx;
}

FunctionMetadataDifferentiabilityKind diffKind;
if (Node->getChild(firstChildIdx)->getKind() ==
NodeKind::DifferentiableFunctionType) {
Expand Down Expand Up @@ -811,7 +828,7 @@ class TypeDecoder {
if (result.isError())
return result;
return Builder.createFunctionType(
parameters, result.getType(), flags, diffKind);
parameters, result.getType(), flags, diffKind, globalActorType);
}
case NodeKind::ImplFunctionType: {
auto calleeConvention = ImplParameterConvention::Direct_Unowned;
Expand Down
22 changes: 17 additions & 5 deletions include/swift/Reflection/TypeRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -462,10 +462,12 @@ class FunctionTypeRef final : public TypeRef {
const TypeRef *Result;
FunctionTypeFlags Flags;
FunctionMetadataDifferentiabilityKind DifferentiabilityKind;
const TypeRef *GlobalActor;

static TypeRefID Profile(const std::vector<Param> &Parameters,
const TypeRef *Result, FunctionTypeFlags Flags,
FunctionMetadataDifferentiabilityKind DiffKind) {
FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor) {
TypeRefID ID;
for (const auto &Param : Parameters) {
ID.addString(Param.getLabel().str());
Expand All @@ -475,21 +477,27 @@ class FunctionTypeRef final : public TypeRef {
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
ID.addInteger(static_cast<uint64_t>(DiffKind.getIntValue()));
ID.addPointer(GlobalActor);

return ID;
}

public:
FunctionTypeRef(std::vector<Param> Params, const TypeRef *Result,
FunctionTypeFlags Flags,
FunctionMetadataDifferentiabilityKind DiffKind)
FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor)
: TypeRef(TypeRefKind::Function), Parameters(Params), Result(Result),
Flags(Flags), DifferentiabilityKind(DiffKind) {}
Flags(Flags), DifferentiabilityKind(DiffKind),
GlobalActor(GlobalActor) {}

template <typename Allocator>
static const FunctionTypeRef *create(
Allocator &A, std::vector<Param> Params, const TypeRef *Result,
FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind) {
FIND_OR_CREATE_TYPEREF(A, FunctionTypeRef, Params, Result, Flags, DiffKind);
FunctionTypeFlags Flags, FunctionMetadataDifferentiabilityKind DiffKind,
const TypeRef *GlobalActor) {
FIND_OR_CREATE_TYPEREF(
A, FunctionTypeRef, Params, Result, Flags, DiffKind, GlobalActor);
}

const std::vector<Param> &getParameters() const { return Parameters; };
Expand All @@ -506,6 +514,10 @@ class FunctionTypeRef final : public TypeRef {
return DifferentiabilityKind;
}

const TypeRef *getGlobalActor() const {
return GlobalActor;
}

static bool classof(const TypeRef *TR) {
return TR->getKind() == TypeRefKind::Function;
}
Expand Down
9 changes: 6 additions & 3 deletions include/swift/Reflection/TypeRefBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,10 @@ class TypeRefBuilder {
const FunctionTypeRef *createFunctionType(
llvm::ArrayRef<remote::FunctionParam<const TypeRef *>> params,
const TypeRef *result, FunctionTypeFlags flags,
FunctionMetadataDifferentiabilityKind diffKind) {
return FunctionTypeRef::create(*this, params, result, flags, diffKind);
FunctionMetadataDifferentiabilityKind diffKind,
const TypeRef *globalActor) {
return FunctionTypeRef::create(
*this, params, result, flags, diffKind, globalActor);
}

const FunctionTypeRef *createImplFunctionType(
Expand Down Expand Up @@ -472,7 +474,8 @@ class TypeRefBuilder {
}

auto result = createTupleType({}, "");
return FunctionTypeRef::create(*this, {}, result, funcFlags, diffKind);
return FunctionTypeRef::create(
*this, {}, result, funcFlags, diffKind, nullptr);
}

const ProtocolCompositionTypeRef *
Expand Down
9 changes: 8 additions & 1 deletion include/swift/Remote/MetadataReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,13 @@ class MetadataReader {
.withEscaping(Function->isEscaping())
.withDifferentiable(Function->isDifferentiable());

BuiltType globalActor = BuiltType();
if (Function->hasGlobalActor()) {
globalActor = readTypeFromMetadata(Function->getGlobalActor());
if (globalActor)
flags = flags.withGlobalActor(true);
}

FunctionMetadataDifferentiabilityKind diffKind;
switch (Function->getDifferentiabilityKind().Value) {
#define CASE(X) \
Expand All @@ -827,7 +834,7 @@ class MetadataReader {
}

auto BuiltFunction = Builder.createFunctionType(
Parameters, Result, flags, diffKind);
Parameters, Result, flags, diffKind, globalActor);
TypeCache[MetadataAddress] = BuiltFunction;
return BuiltFunction;
}
Expand Down
7 changes: 7 additions & 0 deletions include/swift/Runtime/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,13 @@ swift_getFunctionTypeMetadataDifferentiable(
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadataGlobalActor(
FunctionTypeFlags flags, FunctionMetadataDifferentiabilityKind diffKind,
const Metadata *const *parameters, const uint32_t *parameterFlags,
const Metadata *result, const Metadata *globalActor);

SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata0(FunctionTypeFlags flags,
Expand Down
6 changes: 2 additions & 4 deletions lib/AST/ASTDemangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ Type ASTBuilder::createTupleType(ArrayRef<Type> eltTypes, StringRef labels) {
Type ASTBuilder::createFunctionType(
ArrayRef<Demangle::FunctionParam<Type>> params,
Type output, FunctionTypeFlags flags,
FunctionMetadataDifferentiabilityKind diffKind) {
FunctionMetadataDifferentiabilityKind diffKind, Type globalActor) {
// The result type must be materializable.
if (!output->isMaterializable()) return Type();

Expand Down Expand Up @@ -407,14 +407,12 @@ Type ASTBuilder::createFunctionType(
clangFunctionType = Ctx.getClangFunctionType(funcParams, output,
representation);

Type globalActor;
// FIXME: Demangle global actors.

auto einfo =
FunctionType::ExtInfoBuilder(representation, noescape, flags.isThrowing(),
resultDiffKind, clangFunctionType,
globalActor)
.withAsync(flags.isAsync())
.withConcurrent(flags.isSendable())
.build();

return FunctionType::get(funcParams, output, einfo);
Expand Down
17 changes: 5 additions & 12 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2477,6 +2477,11 @@ void ASTMangler::appendFunctionSignature(AnyFunctionType *fn,
appendOperator("Yjl");
break;
}

if (Type globalActor = fn->getGlobalActor()) {
appendType(globalActor);
appendOperator("Yc");
}
}

void ASTMangler::appendFunctionInputType(
Expand Down Expand Up @@ -2876,18 +2881,6 @@ CanType ASTMangler::getDeclTypeForMangling(

Type ty = decl->getInterfaceType()->getReferenceStorageReferent();

// Strip the global actor out of the mangling.
ty = ty.transform([](Type type) {
if (auto fnType = type->getAs<AnyFunctionType>()) {
if (fnType->getGlobalActor()) {
return Type(fnType->withExtInfo(
fnType->getExtInfo().withGlobalActor(Type())));
}
}

return type;
});

auto canTy = ty->getCanonicalType();

if (auto gft = dyn_cast<GenericFunctionType>(canTy)) {
Expand Down
7 changes: 7 additions & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,9 @@ NodePointer Demangler::demangleTypeAnnotation() {
return createNode(Node::Kind::AsyncAnnotation);
case 'b':
return createNode(Node::Kind::ConcurrentFunctionType);
case 'c':
return createWithChild(
Node::Kind::GlobalActorFunctionType, popTypeAndGetChild());
case 'j':
return demangleDifferentiableFunctionType();
case 'k':
Expand Down Expand Up @@ -1280,6 +1283,7 @@ NodePointer Demangler::popFunctionType(Node::Kind kind, bool hasClangType) {
ClangType = demangleClangType();
}
addChild(FuncType, ClangType);
addChild(FuncType, popNode(Node::Kind::GlobalActorFunctionType));
addChild(FuncType, popNode(Node::Kind::DifferentiableFunctionType));
addChild(FuncType, popNode(Node::Kind::ThrowsAnnotation));
addChild(FuncType, popNode(Node::Kind::ConcurrentFunctionType));
Expand Down Expand Up @@ -1316,6 +1320,9 @@ NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
return nullptr;

unsigned FirstChildIdx = 0;
if (FuncType->getChild(FirstChildIdx)->getKind()
== Node::Kind::GlobalActorFunctionType)
++FirstChildIdx;
if (FuncType->getChild(FirstChildIdx)->getKind()
== Node::Kind::DifferentiableFunctionType)
++FirstChildIdx;
Expand Down
14 changes: 14 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ class NodePrinter {
case Node::Kind::GenericTypeParamDecl:
case Node::Kind::ConcurrentFunctionType:
case Node::Kind::DifferentiableFunctionType:
case Node::Kind::GlobalActorFunctionType:
case Node::Kind::AsyncAnnotation:
case Node::Kind::ThrowsAnnotation:
case Node::Kind::EmptyList:
Expand Down Expand Up @@ -810,6 +811,11 @@ class NodePrinter {
unsigned startIndex = 0;
bool isSendable = false, isAsync = false, isThrows = false;
auto diffKind = MangledDifferentiabilityKind::NonDifferentiable;
if (node->getChild(startIndex)->getKind() ==
Node::Kind::GlobalActorFunctionType) {
print(node->getChild(startIndex));
++startIndex;
}
if (node->getChild(startIndex)->getKind() ==
Node::Kind::DifferentiableFunctionType) {
diffKind =
Expand Down Expand Up @@ -2585,6 +2591,14 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
Printer << ' ';
return nullptr;
}
case Node::Kind::GlobalActorFunctionType: {
if (Node->getNumChildren() > 0) {
Printer << '@';
print(Node->getChild(0));
Printer << ' ';
}
return nullptr;
}
case Node::Kind::AsyncAnnotation:
Printer << " async ";
return nullptr;
Expand Down
Loading