Skip to content

Commit

Permalink
Merge pull request #40270 from xedin/thunks-for-dist-methods
Browse files Browse the repository at this point in the history
[Distributed] Implement distributed method accessors
  • Loading branch information
xedin committed Dec 18, 2021
2 parents c4e8844 + d6d9b55 commit 9965df7
Show file tree
Hide file tree
Showing 70 changed files with 2,186 additions and 91 deletions.
2 changes: 2 additions & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ Globals
global ::= opaque-type 'Ho' // opaque type descriptor runtime record
#endif
global ::= protocol-conformance 'Hc' // protocol conformance runtime record
global ::= global 'HF' // accessible function runtime record

global ::= nominal-type 'Mo' // class metadata immediate member base offset

Expand Down Expand Up @@ -218,6 +219,7 @@ types where the metadata itself has unknown layout.)
global ::= global 'TD' // dynamic dispatch thunk
global ::= global 'Td' // direct method reference thunk
global ::= global 'TE' // distributed actor thunk
global ::= global 'TF' // distributed method accessor
global ::= global 'TI' // implementation of a dynamic_replaceable function
global ::= global 'Tu' // async function pointer of a function
global ::= global 'TX' // function pointer of a dynamic_replaceable function
Expand Down
24 changes: 24 additions & 0 deletions include/swift/ABI/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -5036,6 +5036,30 @@ class DynamicReplacementScope
uint32_t getFlags() { return flags; }
};

/// An "accessible" function that can be looked up based on a string key,
/// and then called through a fully-abstracted entry point whose arguments
/// can be constructed in code.
template <typename Runtime>
struct TargetAccessibleFunctionRecord final {
public:
/// The name of the function, which is a unique string assigned to the
/// function so it can be looked up later.
RelativeDirectPointer<const char, /*nullable*/ false> Name;

/// The Swift function type, encoded as a mangled name.
RelativeDirectPointer<const char, /*nullable*/ false> FunctionType;

/// The fully-abstracted function to call.
///
/// Could be a sync or async function pointer depending on flags.
RelativeDirectPointer<void *, /*nullable*/ false> Function;

/// Flags providing more information about the function.
AccessibleFunctionFlags Flags;
};

using AccessibleFunctionRecord = TargetAccessibleFunctionRecord<InProcess>;

} // end namespace swift

#pragma clang diagnostic pop
Expand Down
15 changes: 15 additions & 0 deletions include/swift/ABI/MetadataValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -2312,6 +2312,21 @@ enum class ContinuationStatus : size_t {
Resumed = 2
};

/// Flags that go in a TargetAccessibleFunction structure.
class AccessibleFunctionFlags : public FlagSet<uint32_t> {
public:
enum {
/// Whether this is a "distributed" actor function.
Distributed = 0,
};

explicit AccessibleFunctionFlags(uint32_t bits) : FlagSet(bits) {}
constexpr AccessibleFunctionFlags() {}

/// Whether the this is a "distributed" actor function.
FLAGSET_DEFINE_FLAG_ACCESSORS(Distributed, isDistributed, setDistributed)
};

} // end namespace swift

#endif // SWIFT_ABI_METADATAVALUES_H
2 changes: 2 additions & 0 deletions include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ class ASTMangler : public Mangler {
SwiftAsObjCThunk,
ObjCAsSwiftThunk,
DistributedThunk,
DistributedMethodAccessor,
AccessibleFunctionRecord
};

ASTMangler(bool DWARFMangling = false)
Expand Down
4 changes: 4 additions & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ CONTEXT_NODE(Destructor)
CONTEXT_NODE(DidSet)
NODE(Directness)
NODE(DistributedThunk)
NODE(DistributedMethodAccessor)
NODE(DynamicAttribute)
NODE(DirectMethodReferenceAttribute)
NODE(DynamicSelf)
Expand Down Expand Up @@ -325,5 +326,8 @@ NODE(IndexSubset)
NODE(AsyncAwaitResumePartialFunction)
NODE(AsyncSuspendResumePartialFunction)

// Added in Swift 5.6
NODE(AccessibleFunctionRecord)

#undef CONTEXT_NODE
#undef NODE
44 changes: 43 additions & 1 deletion include/swift/IRGen/Linking.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,16 @@ class LinkEntity {
/// name is known.
/// The pointer is a const char* of the name.
KnownAsyncFunctionPointer,

/// The pointer is SILFunction*
DistributedMethodAccessor,
/// An async function pointer for a distributed method accessor.
/// The pointer is a SILFunction*.
DistributedMethodAccessorAsyncPointer,

/// Accessible function record, which describes a function that can be
/// looked up by name by the runtime.
AccessibleFunctionRecord,
};
friend struct llvm::DenseMapInfo<LinkEntity>;

Expand Down Expand Up @@ -1236,6 +1246,13 @@ class LinkEntity {
Kind, unsigned(LinkEntity::Kind::PartialApplyForwarderAsyncFunctionPointer));
break;

case LinkEntity::Kind::DistributedMethodAccessor: {
entity.Data = LINKENTITY_SET_FIELD(
Kind,
unsigned(LinkEntity::Kind::DistributedMethodAccessorAsyncPointer));
break;
}

default:
llvm_unreachable("Link entity kind cannot have an async function pointer");
}
Expand Down Expand Up @@ -1263,6 +1280,24 @@ class LinkEntity {
return entity;
}

static LinkEntity forDistributedMethodAccessor(SILFunction *method) {
LinkEntity entity;
entity.Pointer = method;
entity.SecondaryPointer = nullptr;
entity.Data =
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::DistributedMethodAccessor));
return entity;
}

static LinkEntity forAccessibleFunctionRecord(SILFunction *func) {
LinkEntity entity;
entity.Pointer = func;
entity.SecondaryPointer = nullptr;
entity.Data =
LINKENTITY_SET_FIELD(Kind, unsigned(Kind::AccessibleFunctionRecord));
return entity;
}

LinkEntity getUnderlyingEntityForAsyncFunctionPointer() const {
LinkEntity entity;
entity.Pointer = Pointer;
Expand Down Expand Up @@ -1294,6 +1329,11 @@ class LinkEntity {
Kind, unsigned(LinkEntity::Kind::PartialApplyForwarder));
break;

case LinkEntity::Kind::DistributedMethodAccessorAsyncPointer:
entity.Data = LINKENTITY_SET_FIELD(
Kind, unsigned(LinkEntity::Kind::DistributedMethodAccessor));
break;

default:
llvm_unreachable("Link entity is not an async function pointer");
}
Expand Down Expand Up @@ -1341,7 +1381,9 @@ class LinkEntity {
return getKind() == Kind::AsyncFunctionPointer ||
getKind() == Kind::DynamicallyReplaceableFunctionVariable ||
getKind() == Kind::DynamicallyReplaceableFunctionKey ||
getKind() == Kind::SILFunction;
getKind() == Kind::SILFunction ||
getKind() == Kind::DistributedMethodAccessor ||
getKind() == Kind::AccessibleFunctionRecord;
}

SILFunction *getSILFunction() const {
Expand Down
34 changes: 34 additions & 0 deletions include/swift/Runtime/AccessibleFunction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===---- AcceesibleFunction.h - Runtime accessible functions ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// The runtime interface for functions accessible by name.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_RUNTIME_ACCESSIBLE_FUNCTION_H
#define SWIFT_RUNTIME_ACCESSIBLE_FUNCTION_H

#include "swift/ABI/Metadata.h"

#include <cstdint>

namespace swift {
namespace runtime {

SWIFT_RUNTIME_STDLIB_SPI const AccessibleFunctionRecord *
swift_findAccessibleFunction(const char *targetNameStart,
size_t targetNameLength);

} // end namespace runtime
} // end namespace swift

#endif
22 changes: 20 additions & 2 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ enum IsExactSelfClass_t {
IsNotExactSelfClass,
IsExactSelfClass,
};
enum IsDistributed_t {
IsNotDistributed,
IsDistributed,
};

enum class PerformanceConstraints : uint8_t {
None = 0,
Expand Down Expand Up @@ -294,6 +298,9 @@ class SILFunction
/// invoked with a `self` argument of the exact base class type.
unsigned ExactSelfClass : 1;

/// Check whether this is a distributed method.
unsigned IsDistributed : 1;

/// True if this function is inlined at least once. This means that the
/// debug info keeps a pointer to this function.
unsigned Inlined : 1;
Expand Down Expand Up @@ -373,14 +380,16 @@ class SILFunction
SubclassScope classSubclassScope, Inline_t inlineStrategy,
EffectsKind E, const SILDebugScope *debugScope,
IsDynamicallyReplaceable_t isDynamic,
IsExactSelfClass_t isExactSelfClass);
IsExactSelfClass_t isExactSelfClass,
IsDistributed_t isDistributed);

static SILFunction *
create(SILModule &M, SILLinkage linkage, StringRef name,
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
ProfileCounter entryCount, IsDynamicallyReplaceable_t isDynamic,
IsDistributed_t isDistributed,
IsExactSelfClass_t isExactSelfClass,
IsThunk_t isThunk = IsNotThunk,
SubclassScope classSubclassScope = SubclassScope::NotApplicable,
Expand All @@ -399,7 +408,8 @@ class SILFunction
Inline_t inlineStrategy, EffectsKind E,
const SILDebugScope *DebugScope,
IsDynamicallyReplaceable_t isDynamic,
IsExactSelfClass_t isExactSelfClass);
IsExactSelfClass_t isExactSelfClass,
IsDistributed_t isDistributed);

/// Set has ownership to the given value. True means that the function has
/// ownership, false means it does not.
Expand Down Expand Up @@ -747,6 +757,14 @@ class SILFunction
ExactSelfClass = t;
}

IsDistributed_t isDistributed() const {
return IsDistributed_t(IsDistributed);
}
void
setIsDistributed(IsDistributed_t value = IsDistributed_t::IsDistributed) {
IsDistributed = value;
}

/// Get the DeclContext of this function.
DeclContext *getDeclContext() const { return DeclCtxt; }

Expand Down
5 changes: 4 additions & 1 deletion include/swift/SIL/SILFunctionBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,16 @@ class SILFunctionBuilder {
IsSerialized_t isSerialized,
ProfileCounter entryCount,
IsThunk_t isThunk,
IsDynamicallyReplaceable_t isDynamic);
IsDynamicallyReplaceable_t isDynamic,
IsDistributed_t isDistributed);

/// Return the declaration of a function, or create it if it doesn't exist.
SILFunction *getOrCreateFunction(
SILLocation loc, StringRef name, SILLinkage linkage,
CanSILFunctionType type, IsBare_t isBareSILFunction,
IsTransparent_t isTransparent, IsSerialized_t isSerialized,
IsDynamicallyReplaceable_t isDynamic,
IsDistributed_t isDistributed,
ProfileCounter entryCount = ProfileCounter(),
IsThunk_t isThunk = IsNotThunk,
SubclassScope subclassScope = SubclassScope::NotApplicable);
Expand Down Expand Up @@ -102,6 +104,7 @@ class SILFunctionBuilder {
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
IsTransparent_t isTrans, IsSerialized_t isSerialized,
IsDynamicallyReplaceable_t isDynamic,
IsDistributed_t isDistributed,
ProfileCounter entryCount = ProfileCounter(),
IsThunk_t isThunk = IsNotThunk,
SubclassScope subclassScope = SubclassScope::NotApplicable,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/SIL/TypeSubstCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
ParentFunction->getLocation(), MangledName, SILLinkage::Shared,
ParentFunction->getLoweredFunctionType(), ParentFunction->isBare(),
ParentFunction->isTransparent(), ParentFunction->isSerialized(),
IsNotDynamic, 0, ParentFunction->isThunk(),
IsNotDynamic, IsNotDistributed, 0, ParentFunction->isThunk(),
ParentFunction->getClassSubclassScope());
// Increment the ref count for the inlined function, so it doesn't
// get deleted before we can emit abstract debug info for it.
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,8 @@ void ASTMangler::appendSymbolKind(SymbolKind SKind) {
case SymbolKind::SwiftAsObjCThunk: return appendOperator("To");
case SymbolKind::ObjCAsSwiftThunk: return appendOperator("TO");
case SymbolKind::DistributedThunk: return appendOperator("TE");
case SymbolKind::DistributedMethodAccessor: return appendOperator("TF");
case SymbolKind::AccessibleFunctionRecord: return appendOperator("HF");
}
}

Expand Down
7 changes: 6 additions & 1 deletion lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,14 @@ bool swift::Demangle::isFunctionAttr(Node::Kind kind) {
case Node::Kind::OutlinedBridgedMethod:
case Node::Kind::MergedFunction:
case Node::Kind::DistributedThunk:
case Node::Kind::DistributedMethodAccessor:
case Node::Kind::DynamicallyReplaceableFunctionImpl:
case Node::Kind::DynamicallyReplaceableFunctionKey:
case Node::Kind::DynamicallyReplaceableFunctionVar:
case Node::Kind::AsyncFunctionPointer:
case Node::Kind::AsyncAwaitResumePartialFunction:
case Node::Kind::AsyncSuspendResumePartialFunction:
case Node::Kind::AccessibleFunctionRecord:
return true;
default:
return false;
Expand Down Expand Up @@ -799,7 +801,7 @@ NodePointer Demangler::demangleOperator() {
return createWithChild(
Node::Kind::ProtocolConformanceRefInProtocolModule, popProtocol());

// Runtime records (type/protocol/conformance)
// Runtime records (type/protocol/conformance/function)
case 'c':
return createWithChild(Node::Kind::ProtocolConformanceDescriptorRecord,
popProtocolConformance());
Expand All @@ -809,6 +811,8 @@ NodePointer Demangler::demangleOperator() {
return createWithChild(Node::Kind::OpaqueTypeDescriptorRecord, popNode());
case 'r':
return createWithChild(Node::Kind::ProtocolDescriptorRecord, popProtocol());
case 'F':
return createNode(Node::Kind::AccessibleFunctionRecord);

default:
pushBack();
Expand Down Expand Up @@ -2363,6 +2367,7 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
case 'D': return createNode(Node::Kind::DynamicAttribute);
case 'd': return createNode(Node::Kind::DirectMethodReferenceAttribute);
case 'E': return createNode(Node::Kind::DistributedThunk);
case 'F': return createNode(Node::Kind::DistributedMethodAccessor);
case 'a': return createNode(Node::Kind::PartialApplyObjCForwarder);
case 'A': return createNode(Node::Kind::PartialApplyForwarder);
case 'm': return createNode(Node::Kind::MergedFunction);
Expand Down
12 changes: 12 additions & 0 deletions lib/Demangling/NodePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ class NodePrinter {
case Node::Kind::ProtocolConformanceRefInProtocolModule:
case Node::Kind::ProtocolConformanceRefInOtherModule:
case Node::Kind::DistributedThunk:
case Node::Kind::DistributedMethodAccessor:
case Node::Kind::DynamicallyReplaceableFunctionKey:
case Node::Kind::DynamicallyReplaceableFunctionImpl:
case Node::Kind::DynamicallyReplaceableFunctionVar:
Expand All @@ -585,6 +586,7 @@ class NodePrinter {
case Node::Kind::IndexSubset:
case Node::Kind::AsyncAwaitResumePartialFunction:
case Node::Kind::AsyncSuspendResumePartialFunction:
case Node::Kind::AccessibleFunctionRecord:
return false;
}
printer_unreachable("bad node kind");
Expand Down Expand Up @@ -1997,6 +1999,16 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
Printer << "distributed thunk for ";
}
return nullptr;
case Node::Kind::DistributedMethodAccessor:
if (!Options.ShortenThunk) {
Printer << "distributed method accessor for ";
}
return nullptr;
case Node::Kind::AccessibleFunctionRecord:
if (!Options.ShortenThunk) {
Printer << "accessible function runtime record for ";
}
return nullptr;
case Node::Kind::DynamicallyReplaceableFunctionKey:
if (!Options.ShortenThunk) {
Printer << "dynamically replaceable key for ";
Expand Down

0 comments on commit 9965df7

Please sign in to comment.